From 757076c88d6ebd16cab940f6c42adac72ebc6f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=99=9F=E6=98=8A?= <545403892@qq.com> Date: Wed, 8 May 2024 16:04:22 +0800 Subject: [PATCH] init --- .gitignore | 37 + .mxproject | 56 + Core/Inc/adc.h | 51 + Core/Inc/dac.h | 50 + Core/Inc/dma.h | 52 + Core/Inc/gpio.h | 49 + Core/Inc/i2c.h | 50 + Core/Inc/main.h | 214 + Core/Inc/spi.h | 51 + Core/Inc/stm32_assert.h | 53 + Core/Inc/stm32l4xx_it.h | 81 + Core/Inc/tim.h | 53 + Core/Inc/usart.h | 51 + Core/Src/adc.c | 318 + Core/Src/dac.c | 76 + Core/Src/dma.c | 81 + Core/Src/gpio.c | 222 + Core/Src/i2c.c | 124 + Core/Src/main.c | 242 + Core/Src/spi.c | 148 + Core/Src/stm32l4xx_it.c | 430 + Core/Src/system_stm32l4xx.c | 332 + Core/Src/tim.c | 202 + Core/Src/usart.c | 216 + .../Device/ST/STM32L4xx/Include/stm32l476xx.h | 18502 ++++++++++++++++ .../Device/ST/STM32L4xx/Include/stm32l4xx.h | 303 + .../ST/STM32L4xx/Include/system_stm32l4xx.h | 106 + Drivers/CMSIS/Device/ST/STM32L4xx/LICENSE.txt | 6 + Drivers/CMSIS/Device/ST/STM32L4xx/License.md | 83 + Drivers/CMSIS/Include/cmsis_armcc.h | 894 + Drivers/CMSIS/Include/cmsis_armclang.h | 1444 ++ Drivers/CMSIS/Include/cmsis_armclang_ltm.h | 1891 ++ Drivers/CMSIS/Include/cmsis_compiler.h | 283 + Drivers/CMSIS/Include/cmsis_gcc.h | 2168 ++ Drivers/CMSIS/Include/cmsis_iccarm.h | 964 + Drivers/CMSIS/Include/cmsis_version.h | 39 + Drivers/CMSIS/Include/core_armv81mml.h | 2968 +++ Drivers/CMSIS/Include/core_armv8mbl.h | 1921 ++ Drivers/CMSIS/Include/core_armv8mml.h | 2835 +++ Drivers/CMSIS/Include/core_cm0.h | 952 + Drivers/CMSIS/Include/core_cm0plus.h | 1085 + Drivers/CMSIS/Include/core_cm1.h | 979 + Drivers/CMSIS/Include/core_cm23.h | 1996 ++ Drivers/CMSIS/Include/core_cm3.h | 1937 ++ Drivers/CMSIS/Include/core_cm33.h | 2910 +++ Drivers/CMSIS/Include/core_cm35p.h | 2910 +++ Drivers/CMSIS/Include/core_cm4.h | 2124 ++ Drivers/CMSIS/Include/core_cm7.h | 2725 +++ Drivers/CMSIS/Include/core_sc000.h | 1025 + Drivers/CMSIS/Include/core_sc300.h | 1912 ++ Drivers/CMSIS/Include/mpu_armv7.h | 272 + Drivers/CMSIS/Include/mpu_armv8.h | 346 + Drivers/CMSIS/Include/tz_context.h | 70 + Drivers/CMSIS/LICENSE.txt | 201 + .../Inc/stm32l4xx_ll_adc.h | 8244 +++++++ .../Inc/stm32l4xx_ll_bus.h | 1954 ++ .../Inc/stm32l4xx_ll_cortex.h | 637 + .../Inc/stm32l4xx_ll_crs.h | 785 + .../Inc/stm32l4xx_ll_dac.h | 1979 ++ .../Inc/stm32l4xx_ll_dma.h | 2430 ++ .../Inc/stm32l4xx_ll_dmamux.h | 1981 ++ .../Inc/stm32l4xx_ll_exti.h | 1359 ++ .../Inc/stm32l4xx_ll_gpio.h | 1056 + .../Inc/stm32l4xx_ll_i2c.h | 2272 ++ .../Inc/stm32l4xx_ll_pwr.h | 1675 ++ .../Inc/stm32l4xx_ll_rcc.h | 6233 ++++++ .../Inc/stm32l4xx_ll_spi.h | 1418 ++ .../Inc/stm32l4xx_ll_system.h | 1627 ++ .../Inc/stm32l4xx_ll_tim.h | 5084 +++++ .../Inc/stm32l4xx_ll_usart.h | 4699 ++++ .../Inc/stm32l4xx_ll_utils.h | 329 + Drivers/STM32L4xx_HAL_Driver/LICENSE.txt | 6 + .../Src/stm32l4xx_ll_adc.c | 1062 + .../Src/stm32l4xx_ll_dac.c | 323 + .../Src/stm32l4xx_ll_dma.c | 400 + .../Src/stm32l4xx_ll_exti.c | 288 + .../Src/stm32l4xx_ll_gpio.c | 293 + .../Src/stm32l4xx_ll_i2c.c | 244 + .../Src/stm32l4xx_ll_pwr.c | 82 + .../Src/stm32l4xx_ll_rcc.c | 2039 ++ .../Src/stm32l4xx_ll_spi.c | 295 + .../Src/stm32l4xx_ll_tim.c | 1356 ++ .../Src/stm32l4xx_ll_usart.c | 487 + .../Src/stm32l4xx_ll_utils.c | 913 + MDK-ARM/.gitignore | 15 + MDK-ARM/EventRecorderStub.scvd | 9 + MDK-ARM/JLinkSettings.ini | 44 + MDK-ARM/RTE/_bootload/RTE_Components.h | 21 + MDK-ARM/RTE/_bootload1/RTE_Components.h | 21 + MDK-ARM/RTE/_common/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-epm/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v2.4/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v2.5/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v2/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v24/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v25/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v4/RTE_Components.h | 21 + MDK-ARM/RTE/_controller-v5/RTE_Components.h | 21 + MDK-ARM/RTE/_gui/RTE_Components.h | 21 + MDK-ARM/RTE/_hart/RTE_Components.h | 21 + MDK-ARM/RTE/_update/RTE_Components.h | 21 + MDK-ARM/conf.cppcheck | 30 + MDK-ARM/controller-v2.CTmp | 0 MDK-ARM/controller-v2.uvoptx | 1502 ++ MDK-ARM/controller-v2.uvprojx | 1410 ++ MDK-ARM/controller-v2/ArInp.Scr | 255 + MDK-ARM/output-bootload.bat | 5 + MDK-ARM/output-controller-v24.bat | 18 + MDK-ARM/output-gui.bat | 4 + MDK-ARM/startup_stm32l476xx.s | 422 + Makefile | 18 + Middlewares/ST/ARM/DSP/Inc/arm_math.h | 7157 ++++++ .../ST/ARM/DSP/Lib/arm_cortexM4l_math.lib | Bin 0 -> 2259776 bytes Public/img/GSDT-LOGO-400x127.png | Bin 0 -> 9702 bytes Public/img/icon/1-HART离线.png | Bin 0 -> 1532 bytes Public/img/icon/2-HART在线.png | Bin 0 -> 1218 bytes Public/img/icon/3-解锁.png | Bin 0 -> 2656 bytes Public/img/icon/4-锁定.png | Bin 0 -> 2630 bytes Public/img/icon/5-禁止写.png | Bin 0 -> 3901 bytes Public/img/icon/6-蓝牙.png | Bin 0 -> 1886 bytes Public/img/icon/7-三角.png | Bin 0 -> 1882 bytes Public/img/icon/a-自动模式.png | Bin 0 -> 8157 bytes Public/img/icon/f-禁用模式.png | Bin 0 -> 414 bytes Public/img/icon/hart.png | Bin 0 -> 3222 bytes Public/img/icon/loading-1.png | Bin 0 -> 2646 bytes Public/img/icon/loading-2.png | Bin 0 -> 2666 bytes Public/img/icon/loading-3.png | Bin 0 -> 2585 bytes Public/img/icon/m-手动模式.png | Bin 0 -> 3362 bytes Public/img/icon/s-停止模式.png | Bin 0 -> 3598 bytes Public/img/icon/t-测试.png | Bin 0 -> 443 bytes Public/img/icon/w-等待模式.png | Bin 0 -> 5119 bytes Public/img/icon/正常.png | Bin 0 -> 2577 bytes Public/img/icon/要求维护.png | Bin 0 -> 4383 bytes Public/img/icon/设备故障.png | Bin 0 -> 4657 bytes Public/img/icon/超出规格.png | Bin 0 -> 5096 bytes Public/img/功能检查.png | Bin 0 -> 1796 bytes Public/img/方向圆-向上.png | Bin 0 -> 4719 bytes Public/img/方向圆-向下.png | Bin 0 -> 4639 bytes Public/img/方向圆-向右.png | Bin 0 -> 4582 bytes Public/img/方向圆-向左.png | Bin 0 -> 4578 bytes Public/img/架构图.png | Bin 0 -> 55881 bytes README.md | 63 + Tests/.idea/.gitignore | 8 + Tests/.idea/Tests.iml | 2 + Tests/.idea/modules.xml | 8 + Tests/.idea/vcs.xml | 6 + Tests/Makefile | 61 + Tests/board/test_eeprom_fm24.c | 41 + Tests/board/test_eeprom_m95.c | 113 + Tests/board/test_ntc_3950.c | 42 + Tests/board/test_rtc_rx8010.c | 98 + Tests/test.c | 19 + Tests/test.h | 16 + Tests/test.py | 3 + Tests/test_bsp.c | 781 + Tests/test_bsp.h | 59 + Tests/test_hart.c | 43 + User/app.c | 136 + User/app.h | 86 + User/app_flow.c | 386 + User/app_hart.c | 317 + User/app_hart.h | 16 + User/application/inc/at_hc24.h | 51 + User/application/inc/convert.h | 32 + User/application/inc/diagnosis.h | 126 + User/application/inc/fal_execution.h | 130 + User/application/inc/key.h | 32 + User/application/inc/params.h | 260 + User/application/inc/pdctrl.h | 68 + User/application/mode/mode.c | 337 + User/application/mode/mode.h | 69 + User/application/mode/mode_def.h | 96 + User/application/mode/mode_pwmp_hd.c | 1773 ++ User/application/mode/mode_pwmp_hd.h | 327 + .../智能阀门定位器DAC输出控制模块软件说明.docx | Bin 0 -> 581516 bytes .../智能阀门定位器pwm定频输出软件说明.docx | Bin 0 -> 165748 bytes User/application/src/at_hc24.c | 113 + User/application/src/convert.c | 466 + User/application/src/diagnosis.c | 784 + User/application/src/fal_execution.c | 583 + User/application/src/key.c | 745 + User/application/src/params.c | 346 + User/application/src/params_hart.c | 21 + User/application/src/pdctrl.c | 310 + User/board/inc/board.h | 182 + User/board/inc/eeprom_fm24.h | 100 + User/board/inc/eeprom_lc02b.h | 47 + User/board/inc/eeprom_m95.h | 129 + User/board/inc/leds.h | 55 + User/board/inc/ntc_3950.h | 15 + User/board/inc/rtc_rx8010.h | 93 + User/board/src/board.c | 1061 + User/board/src/eeprom_fm24.c | 178 + User/board/src/eeprom_lc02b.c | 139 + User/board/src/eeprom_m95.c | 339 + User/board/src/leds.c | 170 + User/board/src/ntc_3950.c | 107 + User/board/src/rtc_rx8010.c | 513 + User/entity.h | 438 + User/lib/bootload/bootload.c | 229 + User/lib/bootload/bootload.h | 100 + User/lib/bootload/readme.md | 50 + User/lib/bootload/test_ymodem.c | 79 + User/lib/bootload/ymodem.c | 633 + User/lib/bootload/ymodem.h | 180 + User/lib/control/custom/pid_c.c | 38 + User/lib/control/custom/pid_c.h | 34 + User/lib/control/custom/pid_g.c | 250 + User/lib/control/custom/pid_g.h | 61 + User/lib/control/custom/pid_hd.c | 180 + User/lib/control/custom/pid_hd.h | 66 + User/lib/control/custom/pid_x.c | 481 + User/lib/control/custom/pid_x.h | 71 + User/lib/control/custom/pid_zh.c | 432 + User/lib/control/custom/pid_zh.h | 71 + User/lib/control/custom/独立PID算法开发.md | 26 + User/lib/control/inc/pid.h | 225 + User/lib/control/inc/pid_auto_tune.h | 56 + User/lib/control/src/pid.c | 39 + User/lib/control/src/pid_auto_tune.c | 230 + User/lib/control/src/pid_common.c | 0 User/lib/control/src/pid_fuzzy.c | 519 + User/lib/control/src/pid_neural.c | 97 + User/lib/control/自整定.md | 1 + User/lib/examples/Makefile | 86 + User/lib/examples/simple_aes.c | 40 + User/lib/examples/simple_clist.c | 52 + User/lib/examples/simple_cmac.c | 33 + User/lib/examples/simple_cmd.c | 26 + User/lib/examples/simple_data_analysis.c | 178 + User/lib/examples/simple_sqqueue.c | 53 + User/lib/flashdb/examples/kvdb_basic_sample.c | 50 + .../flashdb/examples/kvdb_type_blob_sample.c | 63 + .../examples/kvdb_type_string_sample.c | 63 + User/lib/flashdb/examples/tsdb_sample.c | 126 + User/lib/flashdb/fal/fal.c | 62 + User/lib/flashdb/fal/fal.h | 151 + User/lib/flashdb/fal/fal_cfg.h | 56 + User/lib/flashdb/fal/fal_def.h | 170 + User/lib/flashdb/fal/fal_flash.c | 79 + User/lib/flashdb/fal/fal_partition.c | 525 + User/lib/flashdb/fal/fal_rtt.c | 934 + User/lib/flashdb/fal_eeprom24_port.c | 52 + User/lib/flashdb/fal_eeprom95_port.c | 80 + User/lib/flashdb/fdb.c | 157 + User/lib/flashdb/fdb_cfg.h | 50 + User/lib/flashdb/fdb_def.h | 390 + User/lib/flashdb/fdb_file.c | 318 + User/lib/flashdb/fdb_kvdb.c | 2199 ++ User/lib/flashdb/fdb_low_lvl.h | 69 + User/lib/flashdb/fdb_tsdb.c | 1022 + User/lib/flashdb/fdb_utils.c | 320 + User/lib/flashdb/flashdb.h | 89 + User/lib/flow/.vscode/c_cpp_properties.json | 18 + User/lib/flow/.vscode/launch.json | 24 + User/lib/flow/.vscode/settings.json | 58 + User/lib/flow/README.md | 244 + User/lib/flow/example.c | 28 + User/lib/flow/flow.h | 129 + User/lib/flow/flow_core.c | 83 + User/lib/flow/flow_core.h | 106 + User/lib/flow/flow_def.h | 37 + User/lib/flow/flow_sem.h | 40 + User/lib/inc/aes.h | 161 + User/lib/inc/clist.h | 49 + User/lib/inc/cmac.h | 63 + User/lib/inc/cmd.h | 49 + User/lib/inc/data_analysis.h | 79 + User/lib/inc/data_type_def.h | 241 + User/lib/inc/debug.h | 21 + User/lib/inc/filter.h | 56 + User/lib/inc/fsm.h | 307 + User/lib/inc/lib.h | 77 + User/lib/inc/log.h | 45 + User/lib/inc/malloc.h | 45 + User/lib/inc/mlist.h | 268 + User/lib/inc/osel_arch.h | 181 + User/lib/inc/pbuf.h | 169 + User/lib/inc/sqqueue.h | 49 + User/lib/menu/menu.c | 901 + User/lib/menu/menu.h | 278 + User/lib/readme.md | 169 + User/lib/src/aes.c | 981 + User/lib/src/clist.c | 338 + User/lib/src/cmac.c | 159 + User/lib/src/cmd.c | 111 + User/lib/src/data_analysis.c | 468 + User/lib/src/debug.c | 45 + User/lib/src/filter.c | 160 + User/lib/src/lib.c | 440 + User/lib/src/malloc.c | 338 + User/lib/src/mlist.c | 149 + User/lib/src/pbuf.c | 401 + User/lib/src/sqqueue.c | 410 + User/lib/unity/unity.c | 2582 +++ User/lib/unity/unity.h | 687 + User/lib/unity/unity_config.h | 241 + User/lib/unity/unity_internals.h | 1181 + User/system/bsp/adcs.c | 403 + User/system/bsp/adcs.h | 217 + User/system/bsp/bsp.h | 51 + User/system/bsp/dacs.c | 49 + User/system/bsp/dacs.h | 55 + User/system/bsp/eeprom.c | 91 + User/system/bsp/eeprom.h | 7 + User/system/bsp/flash.c | 530 + User/system/bsp/flash.h | 1725 ++ User/system/bsp/gpios.c | 76 + User/system/bsp/gpios.h | 144 + User/system/bsp/i2cs.c | 661 + User/system/bsp/i2cs.h | 126 + User/system/bsp/iwdgs.c | 39 + User/system/bsp/iwdgs.h | 45 + User/system/bsp/pwms.c | 0 User/system/bsp/pwms.h | 54 + User/system/bsp/readme.md | 1 + User/system/bsp/spis.c | 491 + User/system/bsp/spis.h | 133 + User/system/bsp/tims.c | 1 + User/system/bsp/tims.h | 102 + User/system/bsp/uarts.c | 380 + User/system/bsp/uarts.h | 132 + User/system/inc/btn.h | 163 + User/system/inc/delay.h | 21 + User/system/inc/sys.h | 38 + User/system/readme.txt | 4 + User/system/src/btn.c | 247 + User/system/src/delay.c | 116 + User/system/src/sys.c | 175 + bash.exe.stackdump | 16 + controller-v2.ioc | 738 + keilkill.bat | 30 + 332 files changed, 165730 insertions(+) create mode 100644 .gitignore create mode 100644 .mxproject create mode 100644 Core/Inc/adc.h create mode 100644 Core/Inc/dac.h create mode 100644 Core/Inc/dma.h create mode 100644 Core/Inc/gpio.h create mode 100644 Core/Inc/i2c.h create mode 100644 Core/Inc/main.h create mode 100644 Core/Inc/spi.h create mode 100644 Core/Inc/stm32_assert.h create mode 100644 Core/Inc/stm32l4xx_it.h create mode 100644 Core/Inc/tim.h create mode 100644 Core/Inc/usart.h create mode 100644 Core/Src/adc.c create mode 100644 Core/Src/dac.c create mode 100644 Core/Src/dma.c create mode 100644 Core/Src/gpio.c create mode 100644 Core/Src/i2c.c create mode 100644 Core/Src/main.c create mode 100644 Core/Src/spi.c create mode 100644 Core/Src/stm32l4xx_it.c create mode 100644 Core/Src/system_stm32l4xx.c create mode 100644 Core/Src/tim.c create mode 100644 Core/Src/usart.c create mode 100644 Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h create mode 100644 Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l4xx.h create mode 100644 Drivers/CMSIS/Device/ST/STM32L4xx/Include/system_stm32l4xx.h create mode 100644 Drivers/CMSIS/Device/ST/STM32L4xx/LICENSE.txt create mode 100644 Drivers/CMSIS/Device/ST/STM32L4xx/License.md create mode 100644 Drivers/CMSIS/Include/cmsis_armcc.h create mode 100644 Drivers/CMSIS/Include/cmsis_armclang.h create mode 100644 Drivers/CMSIS/Include/cmsis_armclang_ltm.h create mode 100644 Drivers/CMSIS/Include/cmsis_compiler.h create mode 100644 Drivers/CMSIS/Include/cmsis_gcc.h create mode 100644 Drivers/CMSIS/Include/cmsis_iccarm.h create mode 100644 Drivers/CMSIS/Include/cmsis_version.h create mode 100644 Drivers/CMSIS/Include/core_armv81mml.h create mode 100644 Drivers/CMSIS/Include/core_armv8mbl.h create mode 100644 Drivers/CMSIS/Include/core_armv8mml.h create mode 100644 Drivers/CMSIS/Include/core_cm0.h create mode 100644 Drivers/CMSIS/Include/core_cm0plus.h create mode 100644 Drivers/CMSIS/Include/core_cm1.h create mode 100644 Drivers/CMSIS/Include/core_cm23.h create mode 100644 Drivers/CMSIS/Include/core_cm3.h create mode 100644 Drivers/CMSIS/Include/core_cm33.h create mode 100644 Drivers/CMSIS/Include/core_cm35p.h create mode 100644 Drivers/CMSIS/Include/core_cm4.h create mode 100644 Drivers/CMSIS/Include/core_cm7.h create mode 100644 Drivers/CMSIS/Include/core_sc000.h create mode 100644 Drivers/CMSIS/Include/core_sc300.h create mode 100644 Drivers/CMSIS/Include/mpu_armv7.h create mode 100644 Drivers/CMSIS/Include/mpu_armv8.h create mode 100644 Drivers/CMSIS/Include/tz_context.h create mode 100644 Drivers/CMSIS/LICENSE.txt create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_adc.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_bus.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_cortex.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_crs.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dac.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dma.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dmamux.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_exti.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_gpio.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_pwr.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_rcc.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_system.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_tim.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usart.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_utils.h create mode 100644 Drivers/STM32L4xx_HAL_Driver/LICENSE.txt create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_adc.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dac.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_i2c.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_spi.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_tim.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c create mode 100644 Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c create mode 100644 MDK-ARM/.gitignore create mode 100644 MDK-ARM/EventRecorderStub.scvd create mode 100644 MDK-ARM/JLinkSettings.ini create mode 100644 MDK-ARM/RTE/_bootload/RTE_Components.h create mode 100644 MDK-ARM/RTE/_bootload1/RTE_Components.h create mode 100644 MDK-ARM/RTE/_common/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-epm/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v2.4/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v2.5/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v2/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v24/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v25/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v4/RTE_Components.h create mode 100644 MDK-ARM/RTE/_controller-v5/RTE_Components.h create mode 100644 MDK-ARM/RTE/_gui/RTE_Components.h create mode 100644 MDK-ARM/RTE/_hart/RTE_Components.h create mode 100644 MDK-ARM/RTE/_update/RTE_Components.h create mode 100644 MDK-ARM/conf.cppcheck create mode 100644 MDK-ARM/controller-v2.CTmp create mode 100644 MDK-ARM/controller-v2.uvoptx create mode 100644 MDK-ARM/controller-v2.uvprojx create mode 100644 MDK-ARM/controller-v2/ArInp.Scr create mode 100644 MDK-ARM/output-bootload.bat create mode 100644 MDK-ARM/output-controller-v24.bat create mode 100644 MDK-ARM/output-gui.bat create mode 100644 MDK-ARM/startup_stm32l476xx.s create mode 100644 Makefile create mode 100644 Middlewares/ST/ARM/DSP/Inc/arm_math.h create mode 100644 Middlewares/ST/ARM/DSP/Lib/arm_cortexM4l_math.lib create mode 100644 Public/img/GSDT-LOGO-400x127.png create mode 100644 Public/img/icon/1-HART离线.png create mode 100644 Public/img/icon/2-HART在线.png create mode 100644 Public/img/icon/3-解锁.png create mode 100644 Public/img/icon/4-锁定.png create mode 100644 Public/img/icon/5-禁止写.png create mode 100644 Public/img/icon/6-蓝牙.png create mode 100644 Public/img/icon/7-三角.png create mode 100644 Public/img/icon/a-自动模式.png create mode 100644 Public/img/icon/f-禁用模式.png create mode 100644 Public/img/icon/hart.png create mode 100644 Public/img/icon/loading-1.png create mode 100644 Public/img/icon/loading-2.png create mode 100644 Public/img/icon/loading-3.png create mode 100644 Public/img/icon/m-手动模式.png create mode 100644 Public/img/icon/s-停止模式.png create mode 100644 Public/img/icon/t-测试.png create mode 100644 Public/img/icon/w-等待模式.png create mode 100644 Public/img/icon/正常.png create mode 100644 Public/img/icon/要求维护.png create mode 100644 Public/img/icon/设备故障.png create mode 100644 Public/img/icon/超出规格.png create mode 100644 Public/img/功能检查.png create mode 100644 Public/img/方向圆-向上.png create mode 100644 Public/img/方向圆-向下.png create mode 100644 Public/img/方向圆-向右.png create mode 100644 Public/img/方向圆-向左.png create mode 100644 Public/img/架构图.png create mode 100644 README.md create mode 100644 Tests/.idea/.gitignore create mode 100644 Tests/.idea/Tests.iml create mode 100644 Tests/.idea/modules.xml create mode 100644 Tests/.idea/vcs.xml create mode 100644 Tests/Makefile create mode 100644 Tests/board/test_eeprom_fm24.c create mode 100644 Tests/board/test_eeprom_m95.c create mode 100644 Tests/board/test_ntc_3950.c create mode 100644 Tests/board/test_rtc_rx8010.c create mode 100644 Tests/test.c create mode 100644 Tests/test.h create mode 100644 Tests/test.py create mode 100644 Tests/test_bsp.c create mode 100644 Tests/test_bsp.h create mode 100644 Tests/test_hart.c create mode 100644 User/app.c create mode 100644 User/app.h create mode 100644 User/app_flow.c create mode 100644 User/app_hart.c create mode 100644 User/app_hart.h create mode 100644 User/application/inc/at_hc24.h create mode 100644 User/application/inc/convert.h create mode 100644 User/application/inc/diagnosis.h create mode 100644 User/application/inc/fal_execution.h create mode 100644 User/application/inc/key.h create mode 100644 User/application/inc/params.h create mode 100644 User/application/inc/pdctrl.h create mode 100644 User/application/mode/mode.c create mode 100644 User/application/mode/mode.h create mode 100644 User/application/mode/mode_def.h create mode 100644 User/application/mode/mode_pwmp_hd.c create mode 100644 User/application/mode/mode_pwmp_hd.h create mode 100644 User/application/mode/说明/智能阀门定位器DAC输出控制模块软件说明.docx create mode 100644 User/application/mode/说明/智能阀门定位器pwm定频输出软件说明.docx create mode 100644 User/application/src/at_hc24.c create mode 100644 User/application/src/convert.c create mode 100644 User/application/src/diagnosis.c create mode 100644 User/application/src/fal_execution.c create mode 100644 User/application/src/key.c create mode 100644 User/application/src/params.c create mode 100644 User/application/src/params_hart.c create mode 100644 User/application/src/pdctrl.c create mode 100644 User/board/inc/board.h create mode 100644 User/board/inc/eeprom_fm24.h create mode 100644 User/board/inc/eeprom_lc02b.h create mode 100644 User/board/inc/eeprom_m95.h create mode 100644 User/board/inc/leds.h create mode 100644 User/board/inc/ntc_3950.h create mode 100644 User/board/inc/rtc_rx8010.h create mode 100644 User/board/src/board.c create mode 100644 User/board/src/eeprom_fm24.c create mode 100644 User/board/src/eeprom_lc02b.c create mode 100644 User/board/src/eeprom_m95.c create mode 100644 User/board/src/leds.c create mode 100644 User/board/src/ntc_3950.c create mode 100644 User/board/src/rtc_rx8010.c create mode 100644 User/entity.h create mode 100644 User/lib/bootload/bootload.c create mode 100644 User/lib/bootload/bootload.h create mode 100644 User/lib/bootload/readme.md create mode 100644 User/lib/bootload/test_ymodem.c create mode 100644 User/lib/bootload/ymodem.c create mode 100644 User/lib/bootload/ymodem.h create mode 100644 User/lib/control/custom/pid_c.c create mode 100644 User/lib/control/custom/pid_c.h create mode 100644 User/lib/control/custom/pid_g.c create mode 100644 User/lib/control/custom/pid_g.h create mode 100644 User/lib/control/custom/pid_hd.c create mode 100644 User/lib/control/custom/pid_hd.h create mode 100644 User/lib/control/custom/pid_x.c create mode 100644 User/lib/control/custom/pid_x.h create mode 100644 User/lib/control/custom/pid_zh.c create mode 100644 User/lib/control/custom/pid_zh.h create mode 100644 User/lib/control/custom/独立PID算法开发.md create mode 100644 User/lib/control/inc/pid.h create mode 100644 User/lib/control/inc/pid_auto_tune.h create mode 100644 User/lib/control/src/pid.c create mode 100644 User/lib/control/src/pid_auto_tune.c create mode 100644 User/lib/control/src/pid_common.c create mode 100644 User/lib/control/src/pid_fuzzy.c create mode 100644 User/lib/control/src/pid_neural.c create mode 100644 User/lib/control/自整定.md create mode 100644 User/lib/examples/Makefile create mode 100644 User/lib/examples/simple_aes.c create mode 100644 User/lib/examples/simple_clist.c create mode 100644 User/lib/examples/simple_cmac.c create mode 100644 User/lib/examples/simple_cmd.c create mode 100644 User/lib/examples/simple_data_analysis.c create mode 100644 User/lib/examples/simple_sqqueue.c create mode 100644 User/lib/flashdb/examples/kvdb_basic_sample.c create mode 100644 User/lib/flashdb/examples/kvdb_type_blob_sample.c create mode 100644 User/lib/flashdb/examples/kvdb_type_string_sample.c create mode 100644 User/lib/flashdb/examples/tsdb_sample.c create mode 100644 User/lib/flashdb/fal/fal.c create mode 100644 User/lib/flashdb/fal/fal.h create mode 100644 User/lib/flashdb/fal/fal_cfg.h create mode 100644 User/lib/flashdb/fal/fal_def.h create mode 100644 User/lib/flashdb/fal/fal_flash.c create mode 100644 User/lib/flashdb/fal/fal_partition.c create mode 100644 User/lib/flashdb/fal/fal_rtt.c create mode 100644 User/lib/flashdb/fal_eeprom24_port.c create mode 100644 User/lib/flashdb/fal_eeprom95_port.c create mode 100644 User/lib/flashdb/fdb.c create mode 100644 User/lib/flashdb/fdb_cfg.h create mode 100644 User/lib/flashdb/fdb_def.h create mode 100644 User/lib/flashdb/fdb_file.c create mode 100644 User/lib/flashdb/fdb_kvdb.c create mode 100644 User/lib/flashdb/fdb_low_lvl.h create mode 100644 User/lib/flashdb/fdb_tsdb.c create mode 100644 User/lib/flashdb/fdb_utils.c create mode 100644 User/lib/flashdb/flashdb.h create mode 100644 User/lib/flow/.vscode/c_cpp_properties.json create mode 100644 User/lib/flow/.vscode/launch.json create mode 100644 User/lib/flow/.vscode/settings.json create mode 100644 User/lib/flow/README.md create mode 100644 User/lib/flow/example.c create mode 100644 User/lib/flow/flow.h create mode 100644 User/lib/flow/flow_core.c create mode 100644 User/lib/flow/flow_core.h create mode 100644 User/lib/flow/flow_def.h create mode 100644 User/lib/flow/flow_sem.h create mode 100644 User/lib/inc/aes.h create mode 100644 User/lib/inc/clist.h create mode 100644 User/lib/inc/cmac.h create mode 100644 User/lib/inc/cmd.h create mode 100644 User/lib/inc/data_analysis.h create mode 100644 User/lib/inc/data_type_def.h create mode 100644 User/lib/inc/debug.h create mode 100644 User/lib/inc/filter.h create mode 100644 User/lib/inc/fsm.h create mode 100644 User/lib/inc/lib.h create mode 100644 User/lib/inc/log.h create mode 100644 User/lib/inc/malloc.h create mode 100644 User/lib/inc/mlist.h create mode 100644 User/lib/inc/osel_arch.h create mode 100644 User/lib/inc/pbuf.h create mode 100644 User/lib/inc/sqqueue.h create mode 100644 User/lib/menu/menu.c create mode 100644 User/lib/menu/menu.h create mode 100644 User/lib/readme.md create mode 100644 User/lib/src/aes.c create mode 100644 User/lib/src/clist.c create mode 100644 User/lib/src/cmac.c create mode 100644 User/lib/src/cmd.c create mode 100644 User/lib/src/data_analysis.c create mode 100644 User/lib/src/debug.c create mode 100644 User/lib/src/filter.c create mode 100644 User/lib/src/lib.c create mode 100644 User/lib/src/malloc.c create mode 100644 User/lib/src/mlist.c create mode 100644 User/lib/src/pbuf.c create mode 100644 User/lib/src/sqqueue.c create mode 100644 User/lib/unity/unity.c create mode 100644 User/lib/unity/unity.h create mode 100644 User/lib/unity/unity_config.h create mode 100644 User/lib/unity/unity_internals.h create mode 100644 User/system/bsp/adcs.c create mode 100644 User/system/bsp/adcs.h create mode 100644 User/system/bsp/bsp.h create mode 100644 User/system/bsp/dacs.c create mode 100644 User/system/bsp/dacs.h create mode 100644 User/system/bsp/eeprom.c create mode 100644 User/system/bsp/eeprom.h create mode 100644 User/system/bsp/flash.c create mode 100644 User/system/bsp/flash.h create mode 100644 User/system/bsp/gpios.c create mode 100644 User/system/bsp/gpios.h create mode 100644 User/system/bsp/i2cs.c create mode 100644 User/system/bsp/i2cs.h create mode 100644 User/system/bsp/iwdgs.c create mode 100644 User/system/bsp/iwdgs.h create mode 100644 User/system/bsp/pwms.c create mode 100644 User/system/bsp/pwms.h create mode 100644 User/system/bsp/readme.md create mode 100644 User/system/bsp/spis.c create mode 100644 User/system/bsp/spis.h create mode 100644 User/system/bsp/tims.c create mode 100644 User/system/bsp/tims.h create mode 100644 User/system/bsp/uarts.c create mode 100644 User/system/bsp/uarts.h create mode 100644 User/system/inc/btn.h create mode 100644 User/system/inc/delay.h create mode 100644 User/system/inc/sys.h create mode 100644 User/system/readme.txt create mode 100644 User/system/src/btn.c create mode 100644 User/system/src/delay.c create mode 100644 User/system/src/sys.c create mode 100644 bash.exe.stackdump create mode 100644 controller-v2.ioc create mode 100644 keilkill.bat diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1ade05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test +*.log +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +.VSCodeCounter +USER/Listings +USER/Objects +build +dist + +/MDK-ARM/.vscode/uv4.log +/MDK-ARM/.cmsis/include +/MDK-ARM/.eide +/MDK-ARM/MDK-ARM.code-workspace +/MDK-ARM/.vscode/settings.json +/MDK-ARM/.vscode/tasks.json +/MDK-ARM/.clang-format +/MDK-ARM/.vscode/uv4.log.lock +/MDK-ARM/*.hex +/MDK-ARM/*.bin +/MDK-ARM/.pack + +MDK-ARM/controller-v2/uc_gui.lib +MDK-ARM/controller-v2/*.hex +Public/出厂文件/output/*.bin +Public/出厂文件/output/*.hex +Public/SIL认证/* + +MDK-ARM/controller-v2/controller.hex diff --git a/.mxproject b/.mxproject new file mode 100644 index 0000000..1f17780 --- /dev/null +++ b/.mxproject @@ -0,0 +1,56 @@ +[PreviousLibFiles] +LibFiles=Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_gpio.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_system.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_adc.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_dma.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_dmamux.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_bus.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_cortex.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_rcc.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_crs.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_utils.h;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_utils.c;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_exti.h;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_pwr.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_dac.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_i2c.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_spi.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_tim.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_usart.h;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_gpio.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_adc.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dma.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dac.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_i2c.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_spi.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_pwr.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_tim.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_usart.c;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_rcc.c;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_gpio.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_system.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_adc.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_dma.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_dmamux.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_bus.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_cortex.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_rcc.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_crs.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_utils.h;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_utils.c;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_exti.h;Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_pwr.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_dac.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_i2c.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_spi.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_tim.h;Drivers\STM32L4xx_HAL_Driver\Inc\stm32l4xx_ll_usart.h;Drivers\CMSIS\Device\ST\STM32L4xx\Include\stm32l476xx.h;Drivers\CMSIS\Device\ST\STM32L4xx\Include\stm32l4xx.h;Drivers\CMSIS\Device\ST\STM32L4xx\Include\system_stm32l4xx.h;Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_armclang_ltm.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv81mml.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm35p.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\tz_context.h; + +[PreviousUsedIarFiles] +SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\dac.c;..\Core\Src\dma.c;..\Core\Src\i2c.c;..\Core\Src\iwdg.c;..\Core\Src\spi.c;..\Core\Src\tim.c;..\Core\Src\usart.c;..\Core\Src\stm32l4xx_it.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_utils.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_gpio.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_adc.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dma.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dac.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_i2c.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_spi.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_pwr.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_tim.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_usart.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_rcc.c;..\Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c;..\Core\Src\system_stm32l4xx.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_utils.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_gpio.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_adc.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dma.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dac.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_i2c.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_spi.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_pwr.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_tim.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_usart.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_rcc.c;..\Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c;..\Core\Src\system_stm32l4xx.c;;; +HeaderPath=..\Drivers\STM32L4xx_HAL_Driver\Inc;..\Drivers\CMSIS\Device\ST\STM32L4xx\Include;..\Drivers\CMSIS\Include;..\Core\Inc; +CDefines=USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:4000000;EXTERNALSAI1_CLOCK_VALUE:2097000;EXTERNALSAI2_CLOCK_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:32000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1;STM32L476xx;USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:4000000;EXTERNALSAI1_CLOCK_VALUE:2097000;EXTERNALSAI2_CLOCK_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:32000;VDD_VALUE:3300;PREFETCH_ENABLE:0;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1; + +[PreviousUsedKeilFiles] +SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\dac.c;..\Core\Src\dma.c;..\Core\Src\i2c.c;..\Core\Src\spi.c;..\Core\Src\tim.c;..\Core\Src\usart.c;..\Core\Src\stm32l4xx_it.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_utils.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_gpio.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_adc.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dma.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dac.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_i2c.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_spi.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_pwr.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_tim.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_usart.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_rcc.c;..\Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c;..\Core\Src\system_stm32l4xx.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_utils.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_exti.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_gpio.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_adc.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dma.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_dac.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_i2c.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_spi.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_pwr.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_tim.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_usart.c;..\Drivers\STM32L4xx_HAL_Driver\Src\stm32l4xx_ll_rcc.c;..\Drivers\CMSIS\Device\ST\STM32L4xx\Source\Templates\system_stm32l4xx.c;..\Core\Src\system_stm32l4xx.c;;; +HeaderPath=..\Drivers\STM32L4xx_HAL_Driver\Inc;..\Drivers\CMSIS\Device\ST\STM32L4xx\Include;..\Drivers\CMSIS\Include;..\Middlewares\ST\ARM\DSP\Inc;..\Core\Inc; +CDefines=USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:16000000;EXTERNALSAI1_CLOCK_VALUE:2097000;EXTERNALSAI2_CLOCK_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:32000;VDD_VALUE:3300;PREFETCH_ENABLE:1;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1;STM32L476xx;USE_FULL_LL_DRIVER;HSE_VALUE:8000000;HSE_STARTUP_TIMEOUT:100;LSE_STARTUP_TIMEOUT:5000;LSE_VALUE:32768;MSI_VALUE:16000000;EXTERNALSAI1_CLOCK_VALUE:2097000;EXTERNALSAI2_CLOCK_VALUE:2097000;HSI_VALUE:16000000;LSI_VALUE:32000;VDD_VALUE:3300;PREFETCH_ENABLE:1;INSTRUCTION_CACHE_ENABLE:1;DATA_CACHE_ENABLE:1; + +[] +SourceFiles=;; + +[PreviousGenFiles] +AdvancedFolderStructure=true +HeaderFileListSize=11 +HeaderFiles#0=..\Core\Inc\gpio.h +HeaderFiles#1=..\Core\Inc\adc.h +HeaderFiles#2=..\Core\Inc\dac.h +HeaderFiles#3=..\Core\Inc\dma.h +HeaderFiles#4=..\Core\Inc\i2c.h +HeaderFiles#5=..\Core\Inc\spi.h +HeaderFiles#6=..\Core\Inc\tim.h +HeaderFiles#7=..\Core\Inc\usart.h +HeaderFiles#8=..\Core\Inc\stm32l4xx_it.h +HeaderFiles#9=..\Core\Inc\stm32_assert.h +HeaderFiles#10=..\Core\Inc\main.h +HeaderFolderListSize=1 +HeaderPath#0=..\Core\Inc +HeaderFiles=; +SourceFileListSize=10 +SourceFiles#0=..\Core\Src\gpio.c +SourceFiles#1=..\Core\Src\adc.c +SourceFiles#2=..\Core\Src\dac.c +SourceFiles#3=..\Core\Src\dma.c +SourceFiles#4=..\Core\Src\i2c.c +SourceFiles#5=..\Core\Src\spi.c +SourceFiles#6=..\Core\Src\tim.c +SourceFiles#7=..\Core\Src\usart.c +SourceFiles#8=..\Core\Src\stm32l4xx_it.c +SourceFiles#9=..\Core\Src\main.c +SourceFolderListSize=1 +SourcePath#0=..\Core\Src +SourceFiles=; + +[ThirdPartyIp] +ThirdPartyIpNumber=1 +ThirdPartyIpName#0=STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0 + +[ThirdPartyIp#STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0] +library=..\Middlewares\ST\ARM\DSP\Lib\arm_cortexM4l_math.lib; +header=..\Middlewares\ST\ARM\DSP\Inc\arm_math.h; + diff --git a/Core/Inc/adc.h b/Core/Inc/adc.h new file mode 100644 index 0000000..4f1acee --- /dev/null +++ b/Core/Inc/adc.h @@ -0,0 +1,51 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file adc.h + * @brief This file contains all the function prototypes for + * the adc.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __ADC_H__ +#define __ADC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_ADC1_Init(void); +void MX_ADC2_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ADC_H__ */ + diff --git a/Core/Inc/dac.h b/Core/Inc/dac.h new file mode 100644 index 0000000..7eea5fd --- /dev/null +++ b/Core/Inc/dac.h @@ -0,0 +1,50 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dac.h + * @brief This file contains all the function prototypes for + * the dac.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __DAC_H__ +#define __DAC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DAC1_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DAC_H__ */ + diff --git a/Core/Inc/dma.h b/Core/Inc/dma.h new file mode 100644 index 0000000..9b1e623 --- /dev/null +++ b/Core/Inc/dma.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.h + * @brief This file contains all the function prototypes for + * the dma.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __DMA_H__ +#define __DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* DMA memory to memory transfer handles -------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DMA_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DMA_H__ */ + diff --git a/Core/Inc/gpio.h b/Core/Inc/gpio.h new file mode 100644 index 0000000..6c03ac7 --- /dev/null +++ b/Core/Inc/gpio.h @@ -0,0 +1,49 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file gpio.h + * @brief This file contains all the function prototypes for + * the gpio.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __GPIO_H__ +#define __GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_GPIO_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif +#endif /*__ GPIO_H__ */ + diff --git a/Core/Inc/i2c.h b/Core/Inc/i2c.h new file mode 100644 index 0000000..16eb53f --- /dev/null +++ b/Core/Inc/i2c.h @@ -0,0 +1,50 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file i2c.h + * @brief This file contains all the function prototypes for + * the i2c.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __I2C_H__ +#define __I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_I2C1_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __I2C_H__ */ + diff --git a/Core/Inc/main.h b/Core/Inc/main.h new file mode 100644 index 0000000..2c3c4ff --- /dev/null +++ b/Core/Inc/main.h @@ -0,0 +1,214 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +#include "stm32l4xx_ll_adc.h" +#include "stm32l4xx_ll_dac.h" +#include "stm32l4xx_ll_dma.h" +#include "stm32l4xx_ll_i2c.h" +#include "stm32l4xx_ll_crs.h" +#include "stm32l4xx_ll_rcc.h" +#include "stm32l4xx_ll_bus.h" +#include "stm32l4xx_ll_system.h" +#include "stm32l4xx_ll_exti.h" +#include "stm32l4xx_ll_cortex.h" +#include "stm32l4xx_ll_utils.h" +#include "stm32l4xx_ll_pwr.h" +#include "stm32l4xx_ll_spi.h" +#include "stm32l4xx_ll_tim.h" +#include "stm32l4xx_ll_usart.h" +#include "stm32l4xx_ll_gpio.h" + +#if defined(USE_FULL_ASSERT) +#include "stm32_assert.h" +#endif /* USE_FULL_ASSERT */ + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +#include "lib.h" +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define PWM_OUT_Pin LL_GPIO_PIN_5 +#define PWM_OUT_GPIO_Port GPIOE +#define RTC_SCL_Pin LL_GPIO_PIN_0 +#define RTC_SCL_GPIO_Port GPIOC +#define RTC_SDA_Pin LL_GPIO_PIN_1 +#define RTC_SDA_GPIO_Port GPIOC +#define SWO1_Pin LL_GPIO_PIN_2 +#define SWO1_GPIO_Port GPIOC +#define SWO2_Pin LL_GPIO_PIN_3 +#define SWO2_GPIO_Port GPIOC +#define ADC_PSB_CHANNEL_Pin LL_GPIO_PIN_1 +#define ADC_PSB_CHANNEL_GPIO_Port GPIOA +#define ADC_BP_CHANNEL_Pin LL_GPIO_PIN_2 +#define ADC_BP_CHANNEL_GPIO_Port GPIOA +#define ADC_IPSB_CHANNEL_Pin LL_GPIO_PIN_3 +#define ADC_IPSB_CHANNEL_GPIO_Port GPIOA +#define ADC_NTC_CHANNEL_Pin LL_GPIO_PIN_4 +#define ADC_NTC_CHANNEL_GPIO_Port GPIOA +#define DAC_CONTROL_Pin LL_GPIO_PIN_5 +#define DAC_CONTROL_GPIO_Port GPIOA +#define ADC_VIP_CHANNEL_Pin LL_GPIO_PIN_6 +#define ADC_VIP_CHANNEL_GPIO_Port GPIOA +#define ADC_DCDC_CHANNEL_Pin LL_GPIO_PIN_7 +#define ADC_DCDC_CHANNEL_GPIO_Port GPIOA +#define ADC_BPA_CHANNEL_Pin LL_GPIO_PIN_4 +#define ADC_BPA_CHANNEL_GPIO_Port GPIOC +#define ADC_BPB_CHANNEL_Pin LL_GPIO_PIN_5 +#define ADC_BPB_CHANNEL_GPIO_Port GPIOC +#define HART_PWR_Pin LL_GPIO_PIN_0 +#define HART_PWR_GPIO_Port GPIOB +#define IP_PWR_Pin LL_GPIO_PIN_1 +#define IP_PWR_GPIO_Port GPIOB +#define IP_H_PWR_Pin LL_GPIO_PIN_2 +#define IP_H_PWR_GPIO_Port GPIOB +#define BP_A_PWR_Pin LL_GPIO_PIN_7 +#define BP_A_PWR_GPIO_Port GPIOE +#define BP_S_PWR_Pin LL_GPIO_PIN_8 +#define BP_S_PWR_GPIO_Port GPIOE +#define BP_B_PWR_Pin LL_GPIO_PIN_9 +#define BP_B_PWR_GPIO_Port GPIOE +#define KEY_AUTO_Pin LL_GPIO_PIN_15 +#define KEY_AUTO_GPIO_Port GPIOE +#define LCD_PWR_Pin LL_GPIO_PIN_10 +#define LCD_PWR_GPIO_Port GPIOB +#define PWM_CONTROL_Pin LL_GPIO_PIN_11 +#define PWM_CONTROL_GPIO_Port GPIOB +#define LCD_CS_Pin LL_GPIO_PIN_12 +#define LCD_CS_GPIO_Port GPIOB +#define LCD_SCK_Pin LL_GPIO_PIN_13 +#define LCD_SCK_GPIO_Port GPIOB +#define LCD_MOSI_Pin LL_GPIO_PIN_15 +#define LCD_MOSI_GPIO_Port GPIOB +#define LCD_DISP_Pin LL_GPIO_PIN_8 +#define LCD_DISP_GPIO_Port GPIOD +#define LED1_Pin LL_GPIO_PIN_9 +#define LED1_GPIO_Port GPIOD +#define LED2_Pin LL_GPIO_PIN_10 +#define LED2_GPIO_Port GPIOD +#define LED3_Pin LL_GPIO_PIN_11 +#define LED3_GPIO_Port GPIOD +#define LED4_Pin LL_GPIO_PIN_12 +#define LED4_GPIO_Port GPIOD +#define LED5_Pin LL_GPIO_PIN_13 +#define LED5_GPIO_Port GPIOD +#define KEY6_Pin LL_GPIO_PIN_14 +#define KEY6_GPIO_Port GPIOD +#define KEY5_Pin LL_GPIO_PIN_15 +#define KEY5_GPIO_Port GPIOD +#define KEY4_Pin LL_GPIO_PIN_6 +#define KEY4_GPIO_Port GPIOC +#define KEY3_Pin LL_GPIO_PIN_7 +#define KEY3_GPIO_Port GPIOC +#define KEY2_Pin LL_GPIO_PIN_8 +#define KEY2_GPIO_Port GPIOC +#define KEY1_Pin LL_GPIO_PIN_9 +#define KEY1_GPIO_Port GPIOC +#define HART_RTS_Pin LL_GPIO_PIN_12 +#define HART_RTS_GPIO_Port GPIOA +#define BLE_RST_Pin LL_GPIO_PIN_15 +#define BLE_RST_GPIO_Port GPIOA +#define HART_RST_Pin LL_GPIO_PIN_10 +#define HART_RST_GPIO_Port GPIOC +#define BLE_TX_Pin LL_GPIO_PIN_12 +#define BLE_TX_GPIO_Port GPIOC +#define HART_CD_Pin LL_GPIO_PIN_0 +#define HART_CD_GPIO_Port GPIOD +#define BLE_RX_Pin LL_GPIO_PIN_2 +#define BLE_RX_GPIO_Port GPIOD +#define EE2_CS_Pin LL_GPIO_PIN_5 +#define EE2_CS_GPIO_Port GPIOD +#define EE1_CS_Pin LL_GPIO_PIN_6 +#define EE1_CS_GPIO_Port GPIOD +#define BLE_PWR_Pin LL_GPIO_PIN_7 +#define BLE_PWR_GPIO_Port GPIOD +#define SPI_CLK_Pin LL_GPIO_PIN_3 +#define SPI_CLK_GPIO_Port GPIOB +#define SPI_MISO_Pin LL_GPIO_PIN_4 +#define SPI_MISO_GPIO_Port GPIOB +#define SPI_MOSI_Pin LL_GPIO_PIN_5 +#define SPI_MOSI_GPIO_Port GPIOB +#define HART_TX_Pin LL_GPIO_PIN_6 +#define HART_TX_GPIO_Port GPIOB +#define HART_RX_Pin LL_GPIO_PIN_7 +#define HART_RX_GPIO_Port GPIOB +#define I2C1_SCL_Pin LL_GPIO_PIN_8 +#define I2C1_SCL_GPIO_Port GPIOB +#define I2C1_SDA_Pin LL_GPIO_PIN_9 +#define I2C1_SDA_GPIO_Port GPIOB +#define I2C2_SCL_Pin LL_GPIO_PIN_0 +#define I2C2_SCL_GPIO_Port GPIOE +#define I2C2_SDA_Pin LL_GPIO_PIN_1 +#define I2C2_SDA_GPIO_Port GPIOE +#ifndef NVIC_PRIORITYGROUP_0 +#define NVIC_PRIORITYGROUP_0 ((uint32_t)0x00000007) /*!< 0 bit for pre-emption priority, + 4 bits for subpriority */ +#define NVIC_PRIORITYGROUP_1 ((uint32_t)0x00000006) /*!< 1 bit for pre-emption priority, + 3 bits for subpriority */ +#define NVIC_PRIORITYGROUP_2 ((uint32_t)0x00000005) /*!< 2 bits for pre-emption priority, + 2 bits for subpriority */ +#define NVIC_PRIORITYGROUP_3 ((uint32_t)0x00000004) /*!< 3 bits for pre-emption priority, + 1 bit for subpriority */ +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) /*!< 4 bits for pre-emption priority, + 0 bit for subpriority */ +#endif + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/Core/Inc/spi.h b/Core/Inc/spi.h new file mode 100644 index 0000000..1ec822e --- /dev/null +++ b/Core/Inc/spi.h @@ -0,0 +1,51 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file spi.h + * @brief This file contains all the function prototypes for + * the spi.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __SPI_H__ +#define __SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_SPI1_Init(void); +void MX_SPI2_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SPI_H__ */ + diff --git a/Core/Inc/stm32_assert.h b/Core/Inc/stm32_assert.h new file mode 100644 index 0000000..ce166a2 --- /dev/null +++ b/Core/Inc/stm32_assert.h @@ -0,0 +1,53 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32_assert.h + * @brief STM32 assert file. + ****************************************************************************** + * @attention + * + * Copyright (c) 2018 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __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/Core/Inc/stm32l4xx_it.h b/Core/Inc/stm32l4xx_it.h new file mode 100644 index 0000000..b53c4be --- /dev/null +++ b/Core/Inc/stm32l4xx_it.h @@ -0,0 +1,81 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32l4xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_IT_H +#define __STM32L4xx_IT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void DMA1_Channel1_IRQHandler(void); +void DMA1_Channel2_IRQHandler(void); +void DMA1_Channel5_IRQHandler(void); +void DMA1_Channel6_IRQHandler(void); +void DMA1_Channel7_IRQHandler(void); +void ADC1_2_IRQHandler(void); +void I2C1_EV_IRQHandler(void); +void USART1_IRQHandler(void); +void UART5_IRQHandler(void); +void TIM6_DAC_IRQHandler(void); +void TIM7_IRQHandler(void); +void DMA2_Channel1_IRQHandler(void); +void DMA2_Channel2_IRQHandler(void); +void DMA2_Channel6_IRQHandler(void); +void DMA2_Channel7_IRQHandler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_IT_H */ diff --git a/Core/Inc/tim.h b/Core/Inc/tim.h new file mode 100644 index 0000000..a73434e --- /dev/null +++ b/Core/Inc/tim.h @@ -0,0 +1,53 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file tim.h + * @brief This file contains all the function prototypes for + * the tim.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __TIM_H__ +#define __TIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_TIM2_Init(void); +void MX_TIM3_Init(void); +void MX_TIM6_Init(void); +void MX_TIM7_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIM_H__ */ + diff --git a/Core/Inc/usart.h b/Core/Inc/usart.h new file mode 100644 index 0000000..1b6a191 --- /dev/null +++ b/Core/Inc/usart.h @@ -0,0 +1,51 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.h + * @brief This file contains all the function prototypes for + * the usart.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USART_H__ +#define __USART_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_UART5_Init(void); +void MX_USART1_UART_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USART_H__ */ + diff --git a/Core/Src/adc.c b/Core/Src/adc.c new file mode 100644 index 0000000..2a9ea6f --- /dev/null +++ b/Core/Src/adc.c @@ -0,0 +1,318 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file adc.c + * @brief This file provides code for the configuration + * of the ADC instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "adc.h" + +/* USER CODE BEGIN 0 */ +#include "delay.h" +/* USER CODE END 0 */ + +/* ADC1 init function */ +void MX_ADC1_Init(void) +{ + + /* USER CODE BEGIN ADC1_Init 0 */ + + /* USER CODE END ADC1_Init 0 */ + + LL_ADC_InitTypeDef ADC_InitStruct = {0}; + LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; + LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1); + + /* Peripheral clock enable */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + /**ADC1 GPIO Configuration + PA0 ------> ADC1_IN5 + PA1 ------> ADC1_IN6 + PA2 ------> ADC1_IN7 + PA3 ------> ADC1_IN8 + PA4 ------> ADC1_IN9 + PA6 ------> ADC1_IN11 + PA7 ------> ADC1_IN12 + PC4 ------> ADC1_IN13 + PC5 ------> ADC1_IN14 + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_0|ADC_PSB_CHANNEL_Pin|ADC_BP_CHANNEL_Pin|ADC_IPSB_CHANNEL_Pin + |ADC_NTC_CHANNEL_Pin|ADC_VIP_CHANNEL_Pin|ADC_DCDC_CHANNEL_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = ADC_BPA_CHANNEL_Pin|ADC_BPB_CHANNEL_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + LL_GPIO_EnablePinAnalogControl(GPIOA, LL_GPIO_PIN_0|ADC_PSB_CHANNEL_Pin|ADC_BP_CHANNEL_Pin|ADC_IPSB_CHANNEL_Pin + |ADC_NTC_CHANNEL_Pin|ADC_VIP_CHANNEL_Pin|ADC_DCDC_CHANNEL_Pin); + + LL_GPIO_EnablePinAnalogControl(GPIOC, ADC_BPA_CHANNEL_Pin|ADC_BPB_CHANNEL_Pin); + + /* ADC1 DMA Init */ + + /* ADC1 Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMA_REQUEST_0); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_CIRCULAR); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_HALFWORD); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_HALFWORD); + + /* ADC1 interrupt Init */ + NVIC_SetPriority(ADC1_2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),14, 0)); + NVIC_EnableIRQ(ADC1_2_IRQn); + + /* USER CODE BEGIN ADC1_Init 1 */ + + /* USER CODE END ADC1_Init 1 */ + + /** Common config + */ + ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; + ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; + ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE; + LL_ADC_Init(ADC1, &ADC_InitStruct); + ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; + ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS; + ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; + ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS; + ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED; + ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED; + LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct); + LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_CHANNEL_VREFINT|LL_ADC_CHANNEL_TEMPSENSOR); + ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV64; + ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT; + LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct); + + /* Disable ADC deep power down (enabled by default after reset state) */ + LL_ADC_DisableDeepPowerDown(ADC1); + /* Enable ADC internal voltage regulator */ + LL_ADC_EnableInternalRegulator(ADC1); + /* Delay for ADC internal voltage regulator stabilization. */ + /* Compute number of CPU cycles to wait for, from delay in us. */ + /* Note: Variable divided by 2 to compensate partially */ + /* CPU processing cycles (depends on compilation optimization). */ + /* Note: If system core clock frequency is below 200kHz, wait time */ + /* is only a few CPU processing cycles. */ + uint32_t wait_loop_index; + wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10); + while(wait_loop_index != 0) + { + wait_loop_index--; + } + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_5); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_5, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_5, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_6); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_47CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_6, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_7); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SAMPLINGTIME_47CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_7, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_8); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_8, LL_ADC_SAMPLINGTIME_47CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_8, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_5, LL_ADC_CHANNEL_9); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_9, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_6, LL_ADC_CHANNEL_11); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_11, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_11, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_7, LL_ADC_CHANNEL_12); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_12, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_8, LL_ADC_CHANNEL_13); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_13, LL_ADC_SAMPLINGTIME_47CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_13, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_9, LL_ADC_CHANNEL_14); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_14, LL_ADC_SAMPLINGTIME_47CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_14, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_10, LL_ADC_CHANNEL_VREFINT); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_VREFINT, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_11, LL_ADC_CHANNEL_TEMPSENSOR); + LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SINGLE_ENDED); + /* USER CODE BEGIN ADC1_Init 2 */ + + /* USER CODE END ADC1_Init 2 */ + +} +/* ADC2 init function */ +void MX_ADC2_Init(void) +{ + + /* USER CODE BEGIN ADC2_Init 0 */ + + /* USER CODE END ADC2_Init 0 */ + + LL_ADC_InitTypeDef ADC_InitStruct = {0}; + LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0}; + LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1); + + /* Peripheral clock enable */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); + /**ADC2 GPIO Configuration + PA0 ------> ADC2_IN5 + PA1 ------> ADC2_IN6 + */ + GPIO_InitStruct.Pin = LL_GPIO_PIN_0|ADC_PSB_CHANNEL_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + LL_GPIO_EnablePinAnalogControl(GPIOA, LL_GPIO_PIN_0|ADC_PSB_CHANNEL_Pin); + + /* ADC2 DMA Init */ + + /* ADC2 Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMA_REQUEST_0); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_CIRCULAR); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_HALFWORD); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_HALFWORD); + + /* ADC2 interrupt Init */ + NVIC_SetPriority(ADC1_2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),14, 0)); + NVIC_EnableIRQ(ADC1_2_IRQn); + + /* USER CODE BEGIN ADC2_Init 1 */ + + /* USER CODE END ADC2_Init 1 */ + + /** Common config + */ + ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B; + ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; + ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE; + LL_ADC_Init(ADC2, &ADC_InitStruct); + ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; + ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS; + ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; + ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_CONTINUOUS; + ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_UNLIMITED; + ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED; + LL_ADC_REG_Init(ADC2, &ADC_REG_InitStruct); + ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV64; + LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC2), &ADC_CommonInitStruct); + LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC2), LL_ADC_PATH_INTERNAL_NONE); + + /* Disable ADC deep power down (enabled by default after reset state) */ + LL_ADC_DisableDeepPowerDown(ADC2); + /* Enable ADC internal voltage regulator */ + LL_ADC_EnableInternalRegulator(ADC2); + /* Delay for ADC internal voltage regulator stabilization. */ + /* Compute number of CPU cycles to wait for, from delay in us. */ + /* Note: Variable divided by 2 to compensate partially */ + /* CPU processing cycles (depends on compilation optimization). */ + /* Note: If system core clock frequency is below 200kHz, wait time */ + /* is only a few CPU processing cycles. */ + uint32_t wait_loop_index; + wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10); + while(wait_loop_index != 0) + { + wait_loop_index--; + } + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_5); + LL_ADC_SetChannelSamplingTime(ADC2, LL_ADC_CHANNEL_5, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC2, LL_ADC_CHANNEL_5, LL_ADC_SINGLE_ENDED); + + /** Configure Regular Channel + */ + LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_6); + LL_ADC_SetChannelSamplingTime(ADC2, LL_ADC_CHANNEL_6, LL_ADC_SAMPLINGTIME_640CYCLES_5); + LL_ADC_SetChannelSingleDiff(ADC2, LL_ADC_CHANNEL_6, LL_ADC_SINGLE_ENDED); + /* USER CODE BEGIN ADC2_Init 2 */ + + /* USER CODE END ADC2_Init 2 */ + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/dac.c b/Core/Src/dac.c new file mode 100644 index 0000000..e34bc7a --- /dev/null +++ b/Core/Src/dac.c @@ -0,0 +1,76 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dac.c + * @brief This file provides code for the configuration + * of the DAC instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "dac.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* DAC1 init function */ +void MX_DAC1_Init(void) +{ + + /* USER CODE BEGIN DAC1_Init 0 */ + + /* USER CODE END DAC1_Init 0 */ + + LL_DAC_InitTypeDef DAC_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DAC1); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); + /**DAC1 GPIO Configuration + PA5 ------> DAC1_OUT2 + */ + GPIO_InitStruct.Pin = DAC_CONTROL_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(DAC_CONTROL_GPIO_Port, &GPIO_InitStruct); + + /* DAC1 interrupt Init */ + NVIC_SetPriority(TIM6_DAC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),6, 0)); + NVIC_EnableIRQ(TIM6_DAC_IRQn); + + /* USER CODE BEGIN DAC1_Init 1 */ + + /* USER CODE END DAC1_Init 1 */ + + /** DAC channel OUT2 config + */ + DAC_InitStruct.TriggerSource = LL_DAC_TRIG_SOFTWARE; + DAC_InitStruct.WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE; + DAC_InitStruct.OutputBuffer = LL_DAC_OUTPUT_BUFFER_DISABLE; + DAC_InitStruct.OutputConnection = LL_DAC_OUTPUT_CONNECT_GPIO; + DAC_InitStruct.OutputMode = LL_DAC_OUTPUT_MODE_NORMAL; + LL_DAC_Init(DAC1, LL_DAC_CHANNEL_2, &DAC_InitStruct); + LL_DAC_DisableTrigger(DAC1, LL_DAC_CHANNEL_2); + /* USER CODE BEGIN DAC1_Init 2 */ + + /* USER CODE END DAC1_Init 2 */ + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/dma.c b/Core/Src/dma.c new file mode 100644 index 0000000..4d46a6c --- /dev/null +++ b/Core/Src/dma.c @@ -0,0 +1,81 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.c + * @brief This file provides code for the configuration + * of all the requested memory to memory DMA transfers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure DMA */ +/*----------------------------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Enable DMA controller clock + */ +void MX_DMA_Init(void) +{ + + /* Init with LL driver */ + /* DMA controller clock enable */ + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2); + + /* DMA interrupt init */ + /* DMA1_Channel1_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),14, 0)); + NVIC_EnableIRQ(DMA1_Channel1_IRQn); + /* DMA1_Channel2_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA1_Channel2_IRQn); + /* DMA1_Channel5_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),14, 0)); + NVIC_EnableIRQ(DMA1_Channel5_IRQn); + /* DMA1_Channel6_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel6_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA1_Channel6_IRQn); + /* DMA1_Channel7_IRQn interrupt configuration */ + NVIC_SetPriority(DMA1_Channel7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA1_Channel7_IRQn); + /* DMA2_Channel1_IRQn interrupt configuration */ + NVIC_SetPriority(DMA2_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA2_Channel1_IRQn); + /* DMA2_Channel2_IRQn interrupt configuration */ + NVIC_SetPriority(DMA2_Channel2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA2_Channel2_IRQn); + /* DMA2_Channel6_IRQn interrupt configuration */ + NVIC_SetPriority(DMA2_Channel6_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA2_Channel6_IRQn); + /* DMA2_Channel7_IRQn interrupt configuration */ + NVIC_SetPriority(DMA2_Channel7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(DMA2_Channel7_IRQn); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + diff --git a/Core/Src/gpio.c b/Core/Src/gpio.c new file mode 100644 index 0000000..275e3d6 --- /dev/null +++ b/Core/Src/gpio.c @@ -0,0 +1,222 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file gpio.c + * @brief This file provides code for the configuration + * of all used GPIO pins. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "gpio.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure GPIO */ +/*----------------------------------------------------------------------------*/ +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** Configure pins as + * Analog + * Input + * Output + * EVENT_OUT + * EXTI + * Free pins are configured automatically as Analog (this feature is enabled through + * the Code Generation settings) +*/ +void MX_GPIO_Init(void) +{ + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* GPIO Ports Clock Enable */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD); + + /**/ + LL_GPIO_ResetOutputPin(GPIOC, RTC_SCL_Pin|RTC_SDA_Pin|SWO1_Pin|SWO2_Pin + |HART_RST_Pin); + + /**/ + LL_GPIO_ResetOutputPin(GPIOB, HART_PWR_Pin|IP_PWR_Pin|IP_H_PWR_Pin|LCD_PWR_Pin + |LCD_CS_Pin); + + /**/ + LL_GPIO_ResetOutputPin(GPIOE, BP_A_PWR_Pin|BP_S_PWR_Pin|BP_B_PWR_Pin|I2C2_SCL_Pin + |I2C2_SDA_Pin); + + /**/ + LL_GPIO_ResetOutputPin(GPIOD, LCD_DISP_Pin|EE2_CS_Pin|EE1_CS_Pin|BLE_PWR_Pin); + + /**/ + LL_GPIO_ResetOutputPin(GPIOA, HART_RTS_Pin|BLE_RST_Pin); + + /**/ + LL_GPIO_SetOutputPin(GPIOD, LED1_Pin|LED2_Pin|LED3_Pin|LED4_Pin + |LED5_Pin); + + /**/ + GPIO_InitStruct.Pin = LL_GPIO_PIN_2|LL_GPIO_PIN_3|LL_GPIO_PIN_4|LL_GPIO_PIN_6 + |LL_GPIO_PIN_10|LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_13 + |LL_GPIO_PIN_14; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOE, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_14|LL_GPIO_PIN_15|LL_GPIO_PIN_11; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = RTC_SCL_Pin|RTC_SDA_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = SWO1_Pin|SWO2_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = HART_PWR_Pin|IP_PWR_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = IP_H_PWR_Pin|LCD_PWR_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = BP_A_PWR_Pin|BP_S_PWR_Pin|BP_B_PWR_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOE, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = KEY_AUTO_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(KEY_AUTO_GPIO_Port, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LCD_CS_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(LCD_CS_GPIO_Port, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LL_GPIO_PIN_14; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LCD_DISP_Pin|LED1_Pin|LED2_Pin|LED3_Pin + |LED4_Pin|LED5_Pin|EE2_CS_Pin|BLE_PWR_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = KEY6_Pin|KEY5_Pin|HART_CD_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = KEY4_Pin|KEY3_Pin|KEY2_Pin|KEY1_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9|LL_GPIO_PIN_10|LL_GPIO_PIN_11; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = HART_RTS_Pin|BLE_RST_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + LL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = HART_RST_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + LL_GPIO_Init(HART_RST_GPIO_Port, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = LL_GPIO_PIN_1|LL_GPIO_PIN_3|LL_GPIO_PIN_4; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = EE1_CS_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + LL_GPIO_Init(EE1_CS_GPIO_Port, &GPIO_InitStruct); + + /**/ + GPIO_InitStruct.Pin = I2C2_SCL_Pin|I2C2_SDA_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(GPIOE, &GPIO_InitStruct); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ diff --git a/Core/Src/i2c.c b/Core/Src/i2c.c new file mode 100644 index 0000000..ae100d6 --- /dev/null +++ b/Core/Src/i2c.c @@ -0,0 +1,124 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file i2c.c + * @brief This file provides code for the configuration + * of the I2C instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2024 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "i2c.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* I2C1 init function */ +void MX_I2C1_Init(void) +{ + + /* USER CODE BEGIN I2C1_Init 0 */ + + /* USER CODE END I2C1_Init 0 */ + + LL_I2C_InitTypeDef I2C_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + /**I2C1 GPIO Configuration + PB8 ------> I2C1_SCL + PB9 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = I2C1_SCL_Pin|I2C1_SDA_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_4; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1); + + /* I2C1 DMA Init */ + + /* I2C1_RX Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_7, LL_DMA_REQUEST_3); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_7, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MDATAALIGN_BYTE); + + /* I2C1_TX Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_6, LL_DMA_REQUEST_3); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_BYTE); + + /* I2C1 interrupt Init */ + NVIC_SetPriority(I2C1_EV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(I2C1_EV_IRQn); + + /* USER CODE BEGIN I2C1_Init 1 */ + + /* USER CODE END I2C1_Init 1 */ + + /** I2C Initialization + */ + LL_I2C_EnableAutoEndMode(I2C1); + LL_I2C_DisableOwnAddress2(I2C1); + LL_I2C_DisableGeneralCall(I2C1); + LL_I2C_EnableClockStretching(I2C1); + I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; + I2C_InitStruct.Timing = 0x00000E14; + I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; + I2C_InitStruct.DigitalFilter = 0; + I2C_InitStruct.OwnAddress1 = 0; + I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK; + I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; + LL_I2C_Init(I2C1, &I2C_InitStruct); + LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK); + /* USER CODE BEGIN I2C1_Init 2 */ + + /* USER CODE END I2C1_Init 2 */ + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/main.c b/Core/Src/main.c new file mode 100644 index 0000000..1b81630 --- /dev/null +++ b/Core/Src/main.c @@ -0,0 +1,242 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "adc.h" +#include "dac.h" +#include "dma.h" +#include "i2c.h" +#include "spi.h" +#include "tim.h" +#include "usart.h" +#include "gpio.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include +#include "bsp.h" +#include "delay.h" +#include "board.h" +#include "app.h" +#include "test.h" +#include "diagnosis.h" +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +void PeriphCommonClock_Config(void); +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG); + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); + + /* System interrupt init*/ + NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /* SysTick_IRQn interrupt configuration */ + NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); + + /* USER CODE BEGIN Init */ + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* Configure the peripherals common clocks */ + PeriphCommonClock_Config(); + + /* USER CODE BEGIN SysInit */ + delay_init((SystemCoreClock / 1000000)); + delay_ms(500); // wait for power stable + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_DMA_Init(); + MX_ADC1_Init(); + MX_TIM3_Init(); + MX_DAC1_Init(); + MX_SPI2_Init(); + MX_SPI1_Init(); + MX_TIM2_Init(); + MX_UART5_Init(); + MX_USART1_UART_Init(); + MX_TIM6_Init(); + MX_TIM7_Init(); + MX_I2C1_Init(); + MX_ADC2_Init(); + /* USER CODE BEGIN 2 */ + + leds_dinit(); // LED Deinitialization + lcd_dinit(); // LCD screen Deinitialization + + my_mem_init(SRAMIN); // Initialize internal memory pool 1 + my_mem_init(SRAMEX); // Initialize external memory pool 2 + board_init(); // Initialize board + app_init(); // Initialize application + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + /* USER CODE END WHILE */ + + /* USER CODE BEGIN 3 */ + app_start(); + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) + { + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + while (LL_PWR_IsActiveFlag_VOS() != 0) + { + } + LL_RCC_HSE_Enable(); + + /* Wait till HSE is ready */ + while (LL_RCC_HSE_IsReady() != 1) + { + } + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) + { + } + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_8); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(4000000); + + LL_SetSystemCoreClock(4000000); +} + +/** + * @brief Peripherals Common Clock Configuration + * @retval None + */ +void PeriphCommonClock_Config(void) +{ + LL_RCC_PLLSAI1_ConfigDomain_ADC(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLSAI1R_DIV_2); + LL_RCC_PLLSAI1_EnableDomain_ADC(); + LL_RCC_PLLSAI1_Enable(); + + /* Wait till PLLSAI1 is ready */ + while (LL_RCC_PLLSAI1_IsReady() != 1) + { + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/Core/Src/spi.c b/Core/Src/spi.c new file mode 100644 index 0000000..93f4afb --- /dev/null +++ b/Core/Src/spi.c @@ -0,0 +1,148 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file spi.c + * @brief This file provides code for the configuration + * of the SPI instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "spi.h" + +/* USER CODE BEGIN 0 */ +#include "delay.h" +/* USER CODE END 0 */ + +/* SPI1 init function */ +void MX_SPI1_Init(void) +{ + + /* USER CODE BEGIN SPI1_Init 0 */ + + /* USER CODE END SPI1_Init 0 */ + + LL_SPI_InitTypeDef SPI_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + /**SPI1 GPIO Configuration + PB3 (JTDO-TRACESWO) ------> SPI1_SCK + PB4 (NJTRST) ------> SPI1_MISO + PB5 ------> SPI1_MOSI + */ + GPIO_InitStruct.Pin = SPI_CLK_Pin|SPI_MISO_Pin|SPI_MOSI_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_5; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USER CODE BEGIN SPI1_Init 1 */ + + /* USER CODE END SPI1_Init 1 */ + SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; + SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; + SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH; + SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; + SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; + SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct.CRCPoly = 7; + LL_SPI_Init(SPI1, &SPI_InitStruct); + LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA); + LL_SPI_DisableNSSPulseMgt(SPI1); + /* USER CODE BEGIN SPI1_Init 2 */ + + /* USER CODE END SPI1_Init 2 */ + +} +/* SPI2 init function */ +void MX_SPI2_Init(void) +{ + + /* USER CODE BEGIN SPI2_Init 0 */ + + /* USER CODE END SPI2_Init 0 */ + + LL_SPI_InitTypeDef SPI_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + /**SPI2 GPIO Configuration + PB13 ------> SPI2_SCK + PB15 ------> SPI2_MOSI + */ + GPIO_InitStruct.Pin = LCD_SCK_Pin|LCD_MOSI_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; + GPIO_InitStruct.Alternate = LL_GPIO_AF_5; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* SPI2 DMA Init */ + + /* SPI2_TX Init */ + LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_5, LL_DMA_REQUEST_1); + + LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_5, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + + LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MDATAALIGN_BYTE); + + /* USER CODE BEGIN SPI2_Init 1 */ + + /* USER CODE END SPI2_Init 1 */ + SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; + 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_SOFT; + SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct.BitOrder = LL_SPI_LSB_FIRST; + SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct.CRCPoly = 7; + LL_SPI_Init(SPI2, &SPI_InitStruct); + LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA); + LL_SPI_DisableNSSPulseMgt(SPI2); + /* USER CODE BEGIN SPI2_Init 2 */ + + /* USER CODE END SPI2_Init 2 */ + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/stm32l4xx_it.c b/Core/Src/stm32l4xx_it.c new file mode 100644 index 0000000..430b63b --- /dev/null +++ b/Core/Src/stm32l4xx_it.c @@ -0,0 +1,430 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32l4xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32l4xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +#include "flow.h" +#include "board.h" +#include "bsp.h" +#include "sys.h" +#include "app.h" + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ +extern uart_t *uarts[APP_UART_MAX]; +extern i2c_t *eeprom_fm24_i2c; +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ + +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M4 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + while (1) + { + } + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + leds_off_all(); + leds_on(LEDS_1_RED); + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Memory management fault. + */ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } +} + +/** + * @brief This function handles Prefetch fault, memory access fault. + */ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Undefined instruction or illegal state. + */ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** + * @brief This function handles Debug monitor. + */ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32L4xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32l4xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles DMA1 channel1 global interrupt. + */ +void DMA1_Channel1_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */ + + /* USER CODE END DMA1_Channel1_IRQn 0 */ + + /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */ + adc_dma_callback(ADCS_1); + adc_dma_callback(ADCS_2); + /* USER CODE END DMA1_Channel1_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 channel2 global interrupt. + */ +void DMA1_Channel2_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel2_IRQn 0 */ + + /* USER CODE END DMA1_Channel2_IRQn 0 */ + + /* USER CODE BEGIN DMA1_Channel2_IRQn 1 */ + + /* USER CODE END DMA1_Channel2_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 channel5 global interrupt. + */ +void DMA1_Channel5_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */ + + /* USER CODE END DMA1_Channel5_IRQn 0 */ + + /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */ + + /* USER CODE END DMA1_Channel5_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 channel6 global interrupt. + */ +void DMA1_Channel6_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */ + + /* USER CODE END DMA1_Channel6_IRQn 0 */ + + /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */ + i2c_dma_callback(eeprom_fm24_i2c); + /* USER CODE END DMA1_Channel6_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 channel7 global interrupt. + */ +void DMA1_Channel7_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Channel7_IRQn 0 */ + + /* USER CODE END DMA1_Channel7_IRQn 0 */ + + /* USER CODE BEGIN DMA1_Channel7_IRQn 1 */ + i2c_dma_callback(eeprom_fm24_i2c); + /* USER CODE END DMA1_Channel7_IRQn 1 */ +} + +/** + * @brief This function handles ADC1 and ADC2 interrupts. + */ +void ADC1_2_IRQHandler(void) +{ + /* USER CODE BEGIN ADC1_2_IRQn 0 */ + + /* USER CODE END ADC1_2_IRQn 0 */ + + /* USER CODE BEGIN ADC1_2_IRQn 1 */ + adc_env_callback(ADCS_1); + adc_env_callback(ADCS_2); + /* USER CODE END ADC1_2_IRQn 1 */ +} + +/** + * @brief This function handles I2C1 event interrupt. + */ +void I2C1_EV_IRQHandler(void) +{ + /* USER CODE BEGIN I2C1_EV_IRQn 0 */ + + /* USER CODE END I2C1_EV_IRQn 0 */ + + /* USER CODE BEGIN I2C1_EV_IRQn 1 */ + i2c_ev_callback(eeprom_fm24_i2c); + /* USER CODE END I2C1_EV_IRQn 1 */ +} + +/** + * @brief This function handles USART1 global interrupt. + */ +void USART1_IRQHandler(void) +{ + /* USER CODE BEGIN USART1_IRQn 0 */ + + /* USER CODE END USART1_IRQn 0 */ + /* USER CODE BEGIN USART1_IRQn 1 */ + uart_reception_callback(uarts[APP_UART_1]); + /* USER CODE END USART1_IRQn 1 */ +} + +/** + * @brief This function handles UART5 global interrupt. + */ +void UART5_IRQHandler(void) +{ + /* USER CODE BEGIN UART5_IRQn 0 */ + + /* USER CODE END UART5_IRQn 0 */ + /* USER CODE BEGIN UART5_IRQn 1 */ + uart_reception_callback(uarts[APP_UART_2]); + /* USER CODE END UART5_IRQn 1 */ +} + +/** + * @brief This function handles TIM6 global interrupt, DAC channel1 and channel2 underrun error interrupts. + */ +void TIM6_DAC_IRQHandler(void) +{ + /* USER CODE BEGIN TIM6_DAC_IRQn 0 */ + + /* USER CODE END TIM6_DAC_IRQn 0 */ + + /* USER CODE BEGIN TIM6_DAC_IRQn 1 */ + if (IS_TIM_IT_FLAG(TIM6)) + { + TIM_IRQ_HANDLER(TIM6); + FLOW_TICK_UPDATE(); + LL_IncTick(); + } + /* USER CODE END TIM6_DAC_IRQn 1 */ +} + +/** + * @brief This function handles TIM7 global interrupt. + */ +void TIM7_IRQHandler(void) +{ + /* USER CODE BEGIN TIM7_IRQn 0 */ + + /* USER CODE END TIM7_IRQn 0 */ + /* USER CODE BEGIN TIM7_IRQn 1 */ + if (IS_TIM_IT_FLAG(TIM7)) + { + TIM_IRQ_HANDLER(TIM7); + mode_process(); + } + + /* USER CODE END TIM7_IRQn 1 */ +} + +/** + * @brief This function handles DMA2 channel1 global interrupt. + */ +void DMA2_Channel1_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel1_IRQn 0 */ + + /* USER CODE END DMA2_Channel1_IRQn 0 */ + + /* USER CODE BEGIN DMA2_Channel1_IRQn 1 */ + uart_dma_reception_callback(uarts[APP_UART_2]); + /* USER CODE END DMA2_Channel1_IRQn 1 */ +} + +/** + * @brief This function handles DMA2 channel2 global interrupt. + */ +void DMA2_Channel2_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel2_IRQn 0 */ + + /* USER CODE END DMA2_Channel2_IRQn 0 */ + + /* USER CODE BEGIN DMA2_Channel2_IRQn 1 */ + uart_dma_reception_callback(uarts[APP_UART_2]); + /* USER CODE END DMA2_Channel2_IRQn 1 */ +} + +/** + * @brief This function handles DMA2 channel6 global interrupt. + */ +void DMA2_Channel6_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel6_IRQn 0 */ + + /* USER CODE END DMA2_Channel6_IRQn 0 */ + + /* USER CODE BEGIN DMA2_Channel6_IRQn 1 */ + uart_dma_reception_callback(uarts[APP_UART_1]); + /* USER CODE END DMA2_Channel6_IRQn 1 */ +} + +/** + * @brief This function handles DMA2 channel7 global interrupt. + */ +void DMA2_Channel7_IRQHandler(void) +{ + /* USER CODE BEGIN DMA2_Channel7_IRQn 0 */ + + /* USER CODE END DMA2_Channel7_IRQn 0 */ + + /* USER CODE BEGIN DMA2_Channel7_IRQn 1 */ + uart_dma_reception_callback(uarts[APP_UART_1]); + /* USER CODE END DMA2_Channel7_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/system_stm32l4xx.c b/Core/Src/system_stm32l4xx.c new file mode 100644 index 0000000..be9cfee --- /dev/null +++ b/Core/Src/system_stm32l4xx.c @@ -0,0 +1,332 @@ +/** + ****************************************************************************** + * @file system_stm32l4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32l4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * After each device reset the MSI (4 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32l4xx.s" file, to + * configure the system clock before to branch to main program. + * + * This file configures the system clock as follows: + *============================================================================= + *----------------------------------------------------------------------------- + * System Clock source | MSI + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 4000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 4000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 1 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 1 + *----------------------------------------------------------------------------- + * PLL_M | 1 + *----------------------------------------------------------------------------- + * PLL_N | 8 + *----------------------------------------------------------------------------- + * PLL_P | 7 + *----------------------------------------------------------------------------- + * PLL_Q | 2 + *----------------------------------------------------------------------------- + * PLL_R | 2 + *----------------------------------------------------------------------------- + * PLLSAI1_P | NA + *----------------------------------------------------------------------------- + * PLLSAI1_Q | NA + *----------------------------------------------------------------------------- + * PLLSAI1_R | NA + *----------------------------------------------------------------------------- + * PLLSAI2_P | NA + *----------------------------------------------------------------------------- + * PLLSAI2_Q | NA + *----------------------------------------------------------------------------- + * PLLSAI2_R | NA + *----------------------------------------------------------------------------- + * Require 48MHz for USB OTG FS, | Disabled + * SDIO and RNG clock | + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32l4xx_system + * @{ + */ + +/** @addtogroup STM32L4xx_System_Private_Includes + * @{ + */ + +#include "stm32l4xx.h" + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Defines + * @{ + */ + +#if !defined (HSE_VALUE) + #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (MSI_VALUE) + #define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* MSI_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/* Note: Following vector table addresses must be defined in line with linker + configuration. */ +/*!< Uncomment the following line if you need to relocate the vector table + anywhere in Flash or Sram, else the vector table is kept at the automatic + remap of boot address selected */ +/* #define USER_VECT_TAB_ADDRESS */ + +#if defined(USER_VECT_TAB_ADDRESS) +/*!< Uncomment the following line if you need to relocate your vector Table + in Sram else user remap will be done in Flash. */ +/* #define VECT_TAB_SRAM */ + +#if defined(VECT_TAB_SRAM) +#define VECT_TAB_BASE_ADDRESS SRAM1_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#else +#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table base offset field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ + +/******************************************************************************/ +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Variables + * @{ + */ + /* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 4000000U; + + const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; + const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; + const uint32_t MSIRangeTable[12] = {100000U, 200000U, 400000U, 800000U, 1000000U, 2000000U, \ + 4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U}; +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32L4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system. + * @retval None + */ + +void SystemInit(void) +{ +#if defined(USER_VECT_TAB_ADDRESS) + /* Configure the Vector Table location -------------------------------------*/ + SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; +#endif + + /* FPU settings ------------------------------------------------------------*/ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 20U)|(3UL << 22U)); /* set CP10 and CP11 Full Access */ +#endif +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is MSI, SystemCoreClock will contain the MSI_VALUE(*) + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(**) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(***) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(***) + * or HSI_VALUE(*) or MSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) MSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 4 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (***) HSE_VALUE is a constant defined in stm32l4xx_hal.h file (default value + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp, msirange, pllvco, pllsource, pllm, pllr; + + /* Get MSI Range frequency--------------------------------------------------*/ + if ((RCC->CR & RCC_CR_MSIRGSEL) == 0U) + { /* MSISRANGE from RCC_CSR applies */ + msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U; + } + else + { /* MSIRANGE from RCC_CR applies */ + msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U; + } + /*MSI frequency range in HZ*/ + msirange = MSIRangeTable[msirange]; + + /* Get SYSCLK source -------------------------------------------------------*/ + switch (RCC->CFGR & RCC_CFGR_SWS) + { + case 0x00: /* MSI used as system clock source */ + SystemCoreClock = msirange; + break; + + case 0x04: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + + case 0x08: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + + case 0x0C: /* PLL used as system clock source */ + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U ; + + switch (pllsource) + { + case 0x02: /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm); + break; + + case 0x03: /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm); + break; + + default: /* MSI used as PLL clock source */ + pllvco = (msirange / pllm); + break; + } + pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U); + pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U; + SystemCoreClock = pllvco/pllr; + break; + + default: + SystemCoreClock = msirange; + break; + } + /* Compute HCLK clock frequency --------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Core/Src/tim.c b/Core/Src/tim.c new file mode 100644 index 0000000..5e6f948 --- /dev/null +++ b/Core/Src/tim.c @@ -0,0 +1,202 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file tim.c + * @brief This file provides code for the configuration + * of the TIM instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "tim.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* TIM2 init function */ +void MX_TIM2_Init(void) +{ + + /* USER CODE BEGIN TIM2_Init 0 */ + + /* USER CODE END TIM2_Init 0 */ + + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); + + /* USER CODE BEGIN TIM2_Init 1 */ + + /* USER CODE END TIM2_Init 1 */ + TIM_InitStruct.Prescaler = 0; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 3999; + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; + LL_TIM_Init(TIM2, &TIM_InitStruct); + LL_TIM_EnableARRPreload(TIM2); + LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); + LL_TIM_OC_EnablePreload(TIM2, LL_TIM_CHANNEL_CH4); + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct.CompareValue = 0; + TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; + LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH4, &TIM_OC_InitStruct); + LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH4); + LL_TIM_SetOCRefClearInputSource(TIM2, LL_TIM_OCREF_CLR_INT_NC); + LL_TIM_DisableExternalClock(TIM2); + LL_TIM_ConfigETR(TIM2, LL_TIM_ETR_POLARITY_NONINVERTED, LL_TIM_ETR_PRESCALER_DIV1, LL_TIM_ETR_FILTER_FDIV1); + LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(TIM2); + /* USER CODE BEGIN TIM2_Init 2 */ + + /* USER CODE END TIM2_Init 2 */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + /**TIM2 GPIO Configuration + PB11 ------> TIM2_CH4 + */ + GPIO_InitStruct.Pin = PWM_CONTROL_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + 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_1; + LL_GPIO_Init(PWM_CONTROL_GPIO_Port, &GPIO_InitStruct); + +} +/* TIM3 init function */ +void MX_TIM3_Init(void) +{ + + /* USER CODE BEGIN TIM3_Init 0 */ + + /* USER CODE END TIM3_Init 0 */ + + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3); + + /* USER CODE BEGIN TIM3_Init 1 */ + + /* USER CODE END TIM3_Init 1 */ + TIM_InitStruct.Prescaler = 0; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 3999; + TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; + LL_TIM_Init(TIM3, &TIM_InitStruct); + LL_TIM_EnableARRPreload(TIM3); + LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL); + LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH3); + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct.CompareValue = 0; + TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; + LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct); + LL_TIM_OC_DisableFast(TIM3, LL_TIM_CHANNEL_CH3); + LL_TIM_SetOCRefClearInputSource(TIM3, LL_TIM_OCREF_CLR_INT_NC); + LL_TIM_DisableExternalClock(TIM3); + LL_TIM_ConfigETR(TIM3, LL_TIM_ETR_POLARITY_NONINVERTED, LL_TIM_ETR_PRESCALER_DIV1, LL_TIM_ETR_FILTER_FDIV1); + LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(TIM3); + /* USER CODE BEGIN TIM3_Init 2 */ + + /* USER CODE END TIM3_Init 2 */ + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE); + /**TIM3 GPIO Configuration + PE5 ------> TIM3_CH3 + */ + GPIO_InitStruct.Pin = PWM_OUT_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + 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_2; + LL_GPIO_Init(PWM_OUT_GPIO_Port, &GPIO_InitStruct); + +} +/* TIM6 init function */ +void MX_TIM6_Init(void) +{ + + /* USER CODE BEGIN TIM6_Init 0 */ + + /* USER CODE END TIM6_Init 0 */ + + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6); + + /* TIM6 interrupt Init */ + NVIC_SetPriority(TIM6_DAC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),6, 0)); + NVIC_EnableIRQ(TIM6_DAC_IRQn); + + /* USER CODE BEGIN TIM6_Init 1 */ + + /* USER CODE END TIM6_Init 1 */ + TIM_InitStruct.Prescaler = 399; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 99; + LL_TIM_Init(TIM6, &TIM_InitStruct); + LL_TIM_EnableARRPreload(TIM6); + LL_TIM_SetTriggerOutput(TIM6, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(TIM6); + /* USER CODE BEGIN TIM6_Init 2 */ + + /* USER CODE END TIM6_Init 2 */ + +} +/* TIM7 init function */ +void MX_TIM7_Init(void) +{ + + /* USER CODE BEGIN TIM7_Init 0 */ + + /* USER CODE END TIM7_Init 0 */ + + LL_TIM_InitTypeDef TIM_InitStruct = {0}; + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7); + + /* TIM7 interrupt Init */ + NVIC_SetPriority(TIM7_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1, 0)); + NVIC_EnableIRQ(TIM7_IRQn); + + /* USER CODE BEGIN TIM7_Init 1 */ + + /* USER CODE END TIM7_Init 1 */ + TIM_InitStruct.Prescaler = 399; + TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct.Autoreload = 99; + LL_TIM_Init(TIM7, &TIM_InitStruct); + LL_TIM_EnableARRPreload(TIM7); + LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(TIM7); + /* USER CODE BEGIN TIM7_Init 2 */ + + /* USER CODE END TIM7_Init 2 */ + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Core/Src/usart.c b/Core/Src/usart.c new file mode 100644 index 0000000..7e45abc --- /dev/null +++ b/Core/Src/usart.c @@ -0,0 +1,216 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file usart.c + * @brief This file provides code for the configuration + * of the USART instances. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "usart.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* UART5 init function */ +void MX_UART5_Init(void) +{ + + /* USER CODE BEGIN UART5_Init 0 */ + + /* USER CODE END UART5_Init 0 */ + + LL_USART_InitTypeDef UART_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_RCC_SetUARTClockSource(LL_RCC_UART5_CLKSOURCE_PCLK1); + + /* Peripheral clock enable */ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC); + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD); + /**UART5 GPIO Configuration + PC12 ------> UART5_TX + PD2 ------> UART5_RX + */ + GPIO_InitStruct.Pin = BLE_TX_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_8; + LL_GPIO_Init(BLE_TX_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = BLE_RX_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_8; + LL_GPIO_Init(BLE_RX_GPIO_Port, &GPIO_InitStruct); + + /* UART5 DMA Init */ + + /* UART5_RX Init */ + LL_DMA_SetPeriphRequest(DMA2, LL_DMA_CHANNEL_2, LL_DMA_REQUEST_2); + + LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + + LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_2, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE); + + /* UART5_TX Init */ + LL_DMA_SetPeriphRequest(DMA2, LL_DMA_CHANNEL_1, LL_DMA_REQUEST_2); + + LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + + LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_1, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_BYTE); + + /* UART5 interrupt Init */ + NVIC_SetPriority(UART5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(UART5_IRQn); + + /* USER CODE BEGIN UART5_Init 1 */ + + /* USER CODE END UART5_Init 1 */ + UART_InitStruct.BaudRate = 9600; + UART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; + UART_InitStruct.StopBits = LL_USART_STOPBITS_1; + UART_InitStruct.Parity = LL_USART_PARITY_NONE; + UART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; + UART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; + UART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; + LL_USART_Init(UART5, &UART_InitStruct); + LL_USART_ConfigAsyncMode(UART5); + LL_USART_Enable(UART5); + /* USER CODE BEGIN UART5_Init 2 */ + + /* USER CODE END UART5_Init 2 */ + +} +/* USART1 init function */ + +void MX_USART1_UART_Init(void) +{ + + /* USER CODE BEGIN USART1_Init 0 */ + + /* USER CODE END USART1_Init 0 */ + + LL_USART_InitTypeDef USART_InitStruct = {0}; + + LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; + + LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2); + + /* Peripheral clock enable */ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); + + LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); + /**USART1 GPIO Configuration + PB6 ------> USART1_TX + PB7 ------> USART1_RX + */ + GPIO_InitStruct.Pin = HART_TX_Pin|HART_RX_Pin; + GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct.Alternate = LL_GPIO_AF_7; + LL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USART1 DMA Init */ + + /* USART1_RX Init */ + LL_DMA_SetPeriphRequest(DMA2, LL_DMA_CHANNEL_7, LL_DMA_REQUEST_2); + + LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_7, LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + + LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_7, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_7, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_7, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_7, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_7, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_7, LL_DMA_MDATAALIGN_BYTE); + + /* USART1_TX Init */ + LL_DMA_SetPeriphRequest(DMA2, LL_DMA_CHANNEL_6, LL_DMA_REQUEST_2); + + LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + + LL_DMA_SetChannelPriorityLevel(DMA2, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_LOW); + + LL_DMA_SetMode(DMA2, LL_DMA_CHANNEL_6, LL_DMA_MODE_NORMAL); + + LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT); + + LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT); + + LL_DMA_SetPeriphSize(DMA2, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_BYTE); + + LL_DMA_SetMemorySize(DMA2, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_BYTE); + + /* USART1 interrupt Init */ + NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); + NVIC_EnableIRQ(USART1_IRQn); + + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + USART_InitStruct.BaudRate = 1200; + USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_9B; + USART_InitStruct.StopBits = LL_USART_STOPBITS_1; + USART_InitStruct.Parity = LL_USART_PARITY_ODD; + USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; + USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; + USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; + LL_USART_Init(USART1, &USART_InitStruct); + LL_USART_ConfigAsyncMode(USART1); + LL_USART_Enable(USART1); + /* USER CODE BEGIN USART1_Init 2 */ + + /* USER CODE END USART1_Init 2 */ + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h b/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h new file mode 100644 index 0000000..ace1e1f --- /dev/null +++ b/Drivers/CMSIS/Device/ST/STM32L4xx/Include/stm32l476xx.h @@ -0,0 +1,18502 @@ +/** + ****************************************************************************** + * @file stm32l476xx.h + * @author MCD Application Team + * @brief CMSIS STM32L476xx Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + * Copyright (c) 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. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32l476xx + * @{ + */ + +#ifndef __STM32L476xx_H +#define __STM32L476xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Configuration_section_for_CMSIS + * @{ + */ + +/** + * @brief Configuration of the Cortex-M4 Processor and Core Peripherals + */ +#define __CM4_REV 0x0001U /*!< Cortex-M4 revision r0p1 */ +#define __MPU_PRESENT 1U /*!< STM32L4XX provides an MPU */ +#define __NVIC_PRIO_BITS 4U /*!< STM32L4XX uses 4 Bits for the Priority Levels */ +#define __Vendor_SysTickConfig 0U /*!< Set to 1 if different SysTick Config is used */ +#define __FPU_PRESENT 1U /*!< FPU present */ + +/** + * @} + */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32L4XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Cortex-M4 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 3 Cortex-M4 Hard Fault Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */ + PVD_PVM_IRQn = 1, /*!< PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection Interrupts */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Channel1_IRQn = 11, /*!< DMA1 Channel 1 global Interrupt */ + DMA1_Channel2_IRQn = 12, /*!< DMA1 Channel 2 global Interrupt */ + DMA1_Channel3_IRQn = 13, /*!< DMA1 Channel 3 global Interrupt */ + DMA1_Channel4_IRQn = 14, /*!< DMA1 Channel 4 global Interrupt */ + DMA1_Channel5_IRQn = 15, /*!< DMA1 Channel 5 global Interrupt */ + DMA1_Channel6_IRQn = 16, /*!< DMA1 Channel 6 global Interrupt */ + DMA1_Channel7_IRQn = 17, /*!< DMA1 Channel 7 global Interrupt */ + ADC1_2_IRQn = 18, /*!< ADC1, ADC2 SAR global Interrupts */ + CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */ + CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */ + CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */ + CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_TIM15_IRQn = 24, /*!< TIM1 Break interrupt and TIM15 global interrupt */ + TIM1_UP_TIM16_IRQn = 25, /*!< TIM1 Update Interrupt and TIM16 global interrupt */ + TIM1_TRG_COM_TIM17_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM17 global interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + DFSDM1_FLT3_IRQn = 42, /*!< DFSDM1 Filter 3 global Interrupt */ + TIM8_BRK_IRQn = 43, /*!< TIM8 Break Interrupt */ + TIM8_UP_IRQn = 44, /*!< TIM8 Update Interrupt */ + TIM8_TRG_COM_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + ADC3_IRQn = 47, /*!< ADC3 global Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */ + DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */ + DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */ + DMA2_Channel4_IRQn = 59, /*!< DMA2 Channel 4 global Interrupt */ + DMA2_Channel5_IRQn = 60, /*!< DMA2 Channel 5 global Interrupt */ + DFSDM1_FLT0_IRQn = 61, /*!< DFSDM1 Filter 0 global Interrupt */ + DFSDM1_FLT1_IRQn = 62, /*!< DFSDM1 Filter 1 global Interrupt */ + DFSDM1_FLT2_IRQn = 63, /*!< DFSDM1 Filter 2 global Interrupt */ + COMP_IRQn = 64, /*!< COMP1 and COMP2 Interrupts */ + LPTIM1_IRQn = 65, /*!< LP TIM1 interrupt */ + LPTIM2_IRQn = 66, /*!< LP TIM2 interrupt */ + OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */ + DMA2_Channel6_IRQn = 68, /*!< DMA2 Channel 6 global interrupt */ + DMA2_Channel7_IRQn = 69, /*!< DMA2 Channel 7 global interrupt */ + LPUART1_IRQn = 70, /*!< LP UART1 interrupt */ + QUADSPI_IRQn = 71, /*!< Quad SPI global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + SAI1_IRQn = 74, /*!< Serial Audio Interface 1 global interrupt */ + SAI2_IRQn = 75, /*!< Serial Audio Interface 2 global interrupt */ + SWPMI1_IRQn = 76, /*!< Serial Wire Interface 1 global interrupt */ + TSC_IRQn = 77, /*!< Touch Sense Controller global interrupt */ + LCD_IRQn = 78, /*!< LCD global interrupt */ + RNG_IRQn = 80, /*!< RNG global interrupt */ + FPU_IRQn = 81 /*!< FPU global interrupt */ +} IRQn_Type; + +/** + * @} + */ + +#include "core_cm4.h" /* Cortex-M4 processor and core peripherals */ +#include "system_stm32l4xx.h" +#include + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC interrupt and status register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC configuration register 1, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sampling time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sampling time register 2, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, 0x1C */ + __IO uint32_t TR1; /*!< ADC analog watchdog 1 threshold register, Address offset: 0x20 */ + __IO uint32_t TR2; /*!< ADC analog watchdog 2 threshold register, Address offset: 0x24 */ + __IO uint32_t TR3; /*!< ADC analog watchdog 3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x2C */ + __IO uint32_t SQR1; /*!< ADC group regular sequencer register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC group regular sequencer register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC group regular sequencer register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC group regular sequencer register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC group regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x44 */ + uint32_t RESERVED4; /*!< Reserved, 0x48 */ + __IO uint32_t JSQR; /*!< ADC group injected sequencer register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x50 - 0x5C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x70 - 0x7C */ + __IO uint32_t JDR1; /*!< ADC group injected rank 1 data register, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC group injected rank 2 data register, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC group injected rank 3 data register, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC group injected rank 4 data register, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC analog watchdog 1 configuration register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC analog watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t DIFSEL; /*!< ADC differential mode selection register, Address offset: 0xB0 */ + __IO uint32_t CALFACT; /*!< ADC calibration factors, Address offset: 0xB4 */ + +} ADC_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< ADC common status register, Address offset: ADC1 base address + 0x300 */ + uint32_t RESERVED; /*!< Reserved, Address offset: ADC1 base address + 0x304 */ + __IO uint32_t CCR; /*!< ADC common configuration register, Address offset: ADC1 base address + 0x308 */ + __IO uint32_t CDR; /*!< ADC common group regular data register Address offset: ADC1 base address + 0x30C */ +} ADC_Common_TypeDef; + + +/** + * @brief Controller Area Network TxMailBox + */ + +typedef struct +{ + __IO uint32_t TIR; /*!< CAN TX mailbox identifier register */ + __IO uint32_t TDTR; /*!< CAN mailbox data length control and time stamp register */ + __IO uint32_t TDLR; /*!< CAN mailbox data low register */ + __IO uint32_t TDHR; /*!< CAN mailbox data high register */ +} CAN_TxMailBox_TypeDef; + +/** + * @brief Controller Area Network FIFOMailBox + */ + +typedef struct +{ + __IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */ + __IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */ + __IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */ + __IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */ +} CAN_FIFOMailBox_TypeDef; + +/** + * @brief Controller Area Network FilterRegister + */ + +typedef struct +{ + __IO uint32_t FR1; /*!< CAN Filter bank register 1 */ + __IO uint32_t FR2; /*!< CAN Filter bank register 1 */ +} CAN_FilterRegister_TypeDef; + +/** + * @brief Controller Area Network + */ + +typedef struct +{ + __IO uint32_t MCR; /*!< CAN master control register, Address offset: 0x00 */ + __IO uint32_t MSR; /*!< CAN master status register, Address offset: 0x04 */ + __IO uint32_t TSR; /*!< CAN transmit status register, Address offset: 0x08 */ + __IO uint32_t RF0R; /*!< CAN receive FIFO 0 register, Address offset: 0x0C */ + __IO uint32_t RF1R; /*!< CAN receive FIFO 1 register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< CAN interrupt enable register, Address offset: 0x14 */ + __IO uint32_t ESR; /*!< CAN error status register, Address offset: 0x18 */ + __IO uint32_t BTR; /*!< CAN bit timing register, Address offset: 0x1C */ + uint32_t RESERVED0[88]; /*!< Reserved, 0x020 - 0x17F */ + CAN_TxMailBox_TypeDef sTxMailBox[3]; /*!< CAN Tx MailBox, Address offset: 0x180 - 0x1AC */ + CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; /*!< CAN FIFO MailBox, Address offset: 0x1B0 - 0x1CC */ + uint32_t RESERVED1[12]; /*!< Reserved, 0x1D0 - 0x1FF */ + __IO uint32_t FMR; /*!< CAN filter master register, Address offset: 0x200 */ + __IO uint32_t FM1R; /*!< CAN filter mode register, Address offset: 0x204 */ + uint32_t RESERVED2; /*!< Reserved, 0x208 */ + __IO uint32_t FS1R; /*!< CAN filter scale register, Address offset: 0x20C */ + uint32_t RESERVED3; /*!< Reserved, 0x210 */ + __IO uint32_t FFA1R; /*!< CAN filter FIFO assignment register, Address offset: 0x214 */ + uint32_t RESERVED4; /*!< Reserved, 0x218 */ + __IO uint32_t FA1R; /*!< CAN filter activation register, Address offset: 0x21C */ + uint32_t RESERVED5[8]; /*!< Reserved, 0x220-0x23F */ + CAN_FilterRegister_TypeDef sFilterRegister[28]; /*!< CAN Filter Register, Address offset: 0x240-0x31C */ +} CAN_TypeDef; + + +/** + * @brief Comparator + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + uint8_t RESERVED0; /*!< Reserved, 0x05 */ + uint16_t RESERVED1; /*!< Reserved, 0x06 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ + +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + __IO uint32_t APB1FZR1; /*!< Debug MCU APB1 freeze register 1, Address offset: 0x08 */ + __IO uint32_t APB1FZR2; /*!< Debug MCU APB1 freeze register 2, Address offset: 0x0C */ + __IO uint32_t APB2FZ; /*!< Debug MCU APB2 freeze register, Address offset: 0x10 */ +} DBGMCU_TypeDef; + + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CMAR; /*!< DMA channel x memory address register */ +} DMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CSELR; /*!< DMA channel selection register */ +} DMA_Request_TypeDef; + +/* Legacy define */ +#define DMA_request_TypeDef DMA_Request_TypeDef + + +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ + __IO uint32_t IMR1; /*!< EXTI Interrupt mask register 1, Address offset: 0x00 */ + __IO uint32_t EMR1; /*!< EXTI Event mask register 1, Address offset: 0x04 */ + __IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register 1, Address offset: 0x08 */ + __IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register 1, Address offset: 0x0C */ + __IO uint32_t SWIER1; /*!< EXTI Software interrupt event register 1, Address offset: 0x10 */ + __IO uint32_t PR1; /*!< EXTI Pending register 1, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved, 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1C */ + __IO uint32_t IMR2; /*!< EXTI Interrupt mask register 2, Address offset: 0x20 */ + __IO uint32_t EMR2; /*!< EXTI Event mask register 2, Address offset: 0x24 */ + __IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register 2, Address offset: 0x28 */ + __IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register 2, Address offset: 0x2C */ + __IO uint32_t SWIER2; /*!< EXTI Software interrupt event register 2, Address offset: 0x30 */ + __IO uint32_t PR2; /*!< EXTI Pending register 2, Address offset: 0x34 */ +} EXTI_TypeDef; + + +/** + * @brief Firewall + */ + +typedef struct +{ + __IO uint32_t CSSA; /*!< Code Segment Start Address register, Address offset: 0x00 */ + __IO uint32_t CSL; /*!< Code Segment Length register, Address offset: 0x04 */ + __IO uint32_t NVDSSA; /*!< NON volatile data Segment Start Address register, Address offset: 0x08 */ + __IO uint32_t NVDSL; /*!< NON volatile data Segment Length register, Address offset: 0x0C */ + __IO uint32_t VDSSA ; /*!< Volatile data Segment Start Address register, Address offset: 0x10 */ + __IO uint32_t VDSL ; /*!< Volatile data Segment Length register, Address offset: 0x14 */ + uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved2, Address offset: 0x1C */ + __IO uint32_t CR ; /*!< Configuration register, Address offset: 0x20 */ +} FIREWALL_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t PDKEYR; /*!< FLASH power down key register, Address offset: 0x04 */ + __IO uint32_t KEYR; /*!< FLASH key register, Address offset: 0x08 */ + __IO uint32_t OPTKEYR; /*!< FLASH option key register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< FLASH status register, Address offset: 0x10 */ + __IO uint32_t CR; /*!< FLASH control register, Address offset: 0x14 */ + __IO uint32_t ECCR; /*!< FLASH ECC register, Address offset: 0x18 */ + __IO uint32_t RESERVED1; /*!< Reserved1, Address offset: 0x1C */ + __IO uint32_t OPTR; /*!< FLASH option register, Address offset: 0x20 */ + __IO uint32_t PCROP1SR; /*!< FLASH bank1 PCROP start address register, Address offset: 0x24 */ + __IO uint32_t PCROP1ER; /*!< FLASH bank1 PCROP end address register, Address offset: 0x28 */ + __IO uint32_t WRP1AR; /*!< FLASH bank1 WRP area A address register, Address offset: 0x2C */ + __IO uint32_t WRP1BR; /*!< FLASH bank1 WRP area B address register, Address offset: 0x30 */ + uint32_t RESERVED2[4]; /*!< Reserved2, Address offset: 0x34-0x40 */ + __IO uint32_t PCROP2SR; /*!< FLASH bank2 PCROP start address register, Address offset: 0x44 */ + __IO uint32_t PCROP2ER; /*!< FLASH bank2 PCROP end address register, Address offset: 0x48 */ + __IO uint32_t WRP2AR; /*!< FLASH bank2 WRP area A address register, Address offset: 0x4C */ + __IO uint32_t WRP2BR; /*!< FLASH bank2 WRP area B address register, Address offset: 0x50 */ +} FLASH_TypeDef; + + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register, Address offset: 0x8C */ + uint32_t RESERVED0; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ + __IO uint32_t BRR; /*!< GPIO Bit Reset register, Address offset: 0x28 */ + __IO uint32_t ASCR; /*!< GPIO analog switch control register, Address offset: 0x2C */ + +} GPIO_TypeDef; + + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + +/** + * @brief LCD + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LCD control register, Address offset: 0x00 */ + __IO uint32_t FCR; /*!< LCD frame control register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< LCD status register, Address offset: 0x08 */ + __IO uint32_t CLR; /*!< LCD clear register, Address offset: 0x0C */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x10 */ + __IO uint32_t RAM[16]; /*!< LCD display memory, Address offset: 0x14-0x50 */ +} LCD_TypeDef; + +/** + * @brief LPTIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + __IO uint32_t OR; /*!< LPTIM Option register, Address offset: 0x20 */ +} LPTIM_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t LPOTR; /*!< OPAMP offset trimming register for low power mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, used for bits common to several OPAMP instances, Address offset: 0x00 */ +} OPAMP_Common_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x08 */ + __IO uint32_t CR4; /*!< PWR power control register 4, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< PWR power status register 1, Address offset: 0x10 */ + __IO uint32_t SR2; /*!< PWR power status register 2, Address offset: 0x14 */ + __IO uint32_t SCR; /*!< PWR power status reset register, Address offset: 0x18 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t PUCRA; /*!< Pull_up control register of portA, Address offset: 0x20 */ + __IO uint32_t PDCRA; /*!< Pull_Down control register of portA, Address offset: 0x24 */ + __IO uint32_t PUCRB; /*!< Pull_up control register of portB, Address offset: 0x28 */ + __IO uint32_t PDCRB; /*!< Pull_Down control register of portB, Address offset: 0x2C */ + __IO uint32_t PUCRC; /*!< Pull_up control register of portC, Address offset: 0x30 */ + __IO uint32_t PDCRC; /*!< Pull_Down control register of portC, Address offset: 0x34 */ + __IO uint32_t PUCRD; /*!< Pull_up control register of portD, Address offset: 0x38 */ + __IO uint32_t PDCRD; /*!< Pull_Down control register of portD, Address offset: 0x3C */ + __IO uint32_t PUCRE; /*!< Pull_up control register of portE, Address offset: 0x40 */ + __IO uint32_t PDCRE; /*!< Pull_Down control register of portE, Address offset: 0x44 */ + __IO uint32_t PUCRF; /*!< Pull_up control register of portF, Address offset: 0x48 */ + __IO uint32_t PDCRF; /*!< Pull_Down control register of portF, Address offset: 0x4C */ + __IO uint32_t PUCRG; /*!< Pull_up control register of portG, Address offset: 0x50 */ + __IO uint32_t PDCRG; /*!< Pull_Down control register of portG, Address offset: 0x54 */ + __IO uint32_t PUCRH; /*!< Pull_up control register of portH, Address offset: 0x58 */ + __IO uint32_t PDCRH; /*!< Pull_Down control register of portH, Address offset: 0x5C */ +} PWR_TypeDef; + + +/** + * @brief QUAD Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< QUADSPI Control register, Address offset: 0x00 */ + __IO uint32_t DCR; /*!< QUADSPI Device Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< QUADSPI Status register, Address offset: 0x08 */ + __IO uint32_t FCR; /*!< QUADSPI Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DLR; /*!< QUADSPI Data Length register, Address offset: 0x10 */ + __IO uint32_t CCR; /*!< QUADSPI Communication Configuration register, Address offset: 0x14 */ + __IO uint32_t AR; /*!< QUADSPI Address register, Address offset: 0x18 */ + __IO uint32_t ABR; /*!< QUADSPI Alternate Bytes register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< QUADSPI Data register, Address offset: 0x20 */ + __IO uint32_t PSMKR; /*!< QUADSPI Polling Status Mask register, Address offset: 0x24 */ + __IO uint32_t PSMAR; /*!< QUADSPI Polling Status Match register, Address offset: 0x28 */ + __IO uint32_t PIR; /*!< QUADSPI Polling Interval register, Address offset: 0x2C */ + __IO uint32_t LPTR; /*!< QUADSPI Low Power Timeout register, Address offset: 0x30 */ +} QUADSPI_TypeDef; + + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t ICSCR; /*!< RCC internal clock sources calibration register, Address offset: 0x04 */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ + __IO uint32_t PLLCFGR; /*!< RCC system PLL configuration register, Address offset: 0x0C */ + __IO uint32_t PLLSAI1CFGR; /*!< RCC PLL SAI1 configuration register, Address offset: 0x10 */ + __IO uint32_t PLLSAI2CFGR; /*!< RCC PLL SAI2 configuration register, Address offset: 0x14 */ + __IO uint32_t CIER; /*!< RCC clock interrupt enable register, Address offset: 0x18 */ + __IO uint32_t CIFR; /*!< RCC clock interrupt flag register, Address offset: 0x1C */ + __IO uint32_t CICR; /*!< RCC clock interrupt clear register, Address offset: 0x20 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x28 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x2C */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x30 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x34 */ + __IO uint32_t APB1RSTR1; /*!< RCC APB1 peripheral reset register 1, Address offset: 0x38 */ + __IO uint32_t APB1RSTR2; /*!< RCC APB1 peripheral reset register 2, Address offset: 0x3C */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x40 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x44 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clocks enable register, Address offset: 0x48 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clocks enable register, Address offset: 0x4C */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clocks enable register, Address offset: 0x50 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x54 */ + __IO uint32_t APB1ENR1; /*!< RCC APB1 peripheral clocks enable register 1, Address offset: 0x58 */ + __IO uint32_t APB1ENR2; /*!< RCC APB1 peripheral clocks enable register 2, Address offset: 0x5C */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clocks enable register, Address offset: 0x60 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x64 */ + __IO uint32_t AHB1SMENR; /*!< RCC AHB1 peripheral clocks enable in sleep and stop modes register, Address offset: 0x68 */ + __IO uint32_t AHB2SMENR; /*!< RCC AHB2 peripheral clocks enable in sleep and stop modes register, Address offset: 0x6C */ + __IO uint32_t AHB3SMENR; /*!< RCC AHB3 peripheral clocks enable in sleep and stop modes register, Address offset: 0x70 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x74 */ + __IO uint32_t APB1SMENR1; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 1, Address offset: 0x78 */ + __IO uint32_t APB1SMENR2; /*!< RCC APB1 peripheral clocks enable in sleep mode and stop modes register 2, Address offset: 0x7C */ + __IO uint32_t APB2SMENR; /*!< RCC APB2 peripheral clocks enable in sleep mode and stop modes register, Address offset: 0x80 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x84 */ + __IO uint32_t CCIPR; /*!< RCC peripherals independent clock configuration register, Address offset: 0x88 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x8C */ + __IO uint32_t BDCR; /*!< RCC backup domain control register, Address offset: 0x90 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x94 */ +} RCC_TypeDef; + +/** + * @brief Real-Time Clock + */ + +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t reserved; /*!< Reserved */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x40-0x44 */ + __I uint32_t FIFOCNT; /*!< SDMMC FIFO counter register, Address offset: 0x48 */ + uint32_t RESERVED1[13]; /*!< Reserved, 0x4C-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ +} SDMMC_TypeDef; + + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t SR; /*!< SPI Status register, Address offset: 0x08 */ + __IO uint32_t DR; /*!< SPI data register, Address offset: 0x0C */ + __IO uint32_t CRCPR; /*!< SPI CRC polynomial register, Address offset: 0x10 */ + __IO uint32_t RXCRCR; /*!< SPI Rx CRC register, Address offset: 0x14 */ + __IO uint32_t TXCRCR; /*!< SPI Tx CRC register, Address offset: 0x18 */ +} SPI_TypeDef; + + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + + +/** + * @brief System configuration controller + */ + +typedef struct +{ + __IO uint32_t MEMRMP; /*!< SYSCFG memory remap register, Address offset: 0x00 */ + __IO uint32_t CFGR1; /*!< SYSCFG configuration register 1, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t SCSR; /*!< SYSCFG SRAM2 control and status register, Address offset: 0x18 */ + __IO uint32_t CFGR2; /*!< SYSCFG configuration register 2, Address offset: 0x1C */ + __IO uint32_t SWPR; /*!< SYSCFG SRAM2 write protection register, Address offset: 0x20 */ + __IO uint32_t SKR; /*!< SYSCFG SRAM2 key register, Address offset: 0x24 */ +} SYSCFG_TypeDef; + + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + __IO uint32_t OR1; /*!< TIM option register 1, Address offset: 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t OR2; /*!< TIM option register 2, Address offset: 0x60 */ + __IO uint32_t OR3; /*!< TIM option register 3, Address offset: 0x64 */ +} TIM_TypeDef; + + +/** + * @brief Touch Sensing Controller (TSC) + */ + +typedef struct +{ + __IO uint32_t CR; /*!< TSC control register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< TSC interrupt enable register, Address offset: 0x04 */ + __IO uint32_t ICR; /*!< TSC interrupt clear register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< TSC interrupt status register, Address offset: 0x0C */ + __IO uint32_t IOHCR; /*!< TSC I/O hysteresis control register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t IOASCR; /*!< TSC I/O analog switch control register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t IOSCR; /*!< TSC I/O sampling control register, Address offset: 0x20 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t IOCCR; /*!< TSC I/O channel control register, Address offset: 0x28 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t IOGCSR; /*!< TSC I/O group control status register, Address offset: 0x30 */ + __IO uint32_t IOGXCR[8]; /*!< TSC I/O group x counter register, Address offset: 0x34-50 */ +} TSC_TypeDef; + +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint16_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + uint16_t RESERVED2; /*!< Reserved, 0x12 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint16_t RQR; /*!< USART Request register, Address offset: 0x18 */ + uint16_t RESERVED3; /*!< Reserved, 0x1A */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint16_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + uint16_t RESERVED4; /*!< Reserved, 0x26 */ + __IO uint16_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + uint16_t RESERVED5; /*!< Reserved, 0x2A */ +} USART_TypeDef; + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ +} RNG_TypeDef; + +/** + * @brief USB_OTG_Core_register + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h*/ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h*/ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h*/ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch*/ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h*/ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h*/ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h*/ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch*/ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h*/ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h*/ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h*/ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch*/ + uint32_t Reserved30[2]; /*!< Reserved 030h*/ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h*/ + __IO uint32_t CID; /*!< User ID Register 03Ch*/ + __IO uint32_t GSNPSID; /*!< USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /*!< User HW config1 044h*/ + __IO uint32_t GHWCFG2; /*!< User HW config2 048h*/ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch*/ + uint32_t Reserved6; /*!< Reserved 050h*/ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h*/ + __IO uint32_t GPWRDN; /*!< Power Down Register 058h*/ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch*/ + __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 060h*/ + uint32_t Reserved43[39]; /*!< Reserved 064h-0FFh*/ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h*/ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /* dev Configuration Register 800h*/ + __IO uint32_t DCTL; /* dev Control Register 804h*/ + __IO uint32_t DSTS; /* dev Status Register (RO) 808h*/ + uint32_t Reserved0C; /* Reserved 80Ch*/ + __IO uint32_t DIEPMSK; /* dev IN Endpoint Mask 810h*/ + __IO uint32_t DOEPMSK; /* dev OUT Endpoint Mask 814h*/ + __IO uint32_t DAINT; /* dev All Endpoints Itr Reg 818h*/ + __IO uint32_t DAINTMSK; /* dev All Endpoints Itr Mask 81Ch*/ + uint32_t Reserved20; /* Reserved 820h*/ + uint32_t Reserved24; /* Reserved 824h*/ + __IO uint32_t DVBUSDIS; /* dev VBUS discharge Register 828h*/ + __IO uint32_t DVBUSPULSE; /* dev VBUS Pulse Register 82Ch*/ + __IO uint32_t DTHRCTL; /* dev thr 830h*/ + __IO uint32_t DIEPEMPMSK; /* dev empty msk 834h*/ + __IO uint32_t DEACHINT; /* dedicated EP interrupt 838h*/ + __IO uint32_t DEACHMSK; /* dedicated EP msk 83Ch*/ + uint32_t Reserved40; /* Reserved 840h*/ + __IO uint32_t DINEP1MSK; /* dedicated EP mask 844h*/ + uint32_t Reserved44[15]; /* Reserved 848-880h*/ + __IO uint32_t DOUTEP1MSK; /* dedicated EP msk 884h*/ +} USB_OTG_DeviceTypeDef; + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /* dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved 900h + (ep_num * 20h) + 04h*/ + __IO uint32_t DIEPINT; /* dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved 900h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DIEPTSIZ; /* IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h*/ + __IO uint32_t DIEPDMA; /* IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h*/ + __IO uint32_t DTXFSTS; /*IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h*/ + uint32_t Reserved18; /* Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch*/ +} USB_OTG_INEndpointTypeDef; + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /* dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h*/ + uint32_t Reserved04; /* Reserved B00h + (ep_num * 20h) + 04h*/ + __IO uint32_t DOEPINT; /* dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h*/ + uint32_t Reserved0C; /* Reserved B00h + (ep_num * 20h) + 0Ch*/ + __IO uint32_t DOEPTSIZ; /* dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h*/ + __IO uint32_t DOEPDMA; /* dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h*/ + uint32_t Reserved18[2]; /* Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch*/ +} USB_OTG_OUTEndpointTypeDef; + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /* Host Configuration Register 400h*/ + __IO uint32_t HFIR; /* Host Frame Interval Register 404h*/ + __IO uint32_t HFNUM; /* Host Frame Nbr/Frame Remaining 408h*/ + uint32_t Reserved40C; /* Reserved 40Ch*/ + __IO uint32_t HPTXSTS; /* Host Periodic Tx FIFO/ Queue Status 410h*/ + __IO uint32_t HAINT; /* Host All Channels Interrupt Register 414h*/ + __IO uint32_t HAINTMSK; /* Host All Channels Interrupt Mask 418h*/ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; + __IO uint32_t HCSPLT; + __IO uint32_t HCINT; + __IO uint32_t HCINTMSK; + __IO uint32_t HCTSIZ; + __IO uint32_t HCDMA; + uint32_t Reserved[2]; +} USB_OTG_HostChannelTypeDef; + +/** + * @} + */ + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define FLASH_BASE (0x08000000UL) /*!< FLASH(up to 1 MB) base address */ +#define FLASH_END (0x080FFFFFUL) /*!< FLASH END address */ +#define FLASH_BANK1_END (0x0807FFFFUL) /*!< FLASH END address of bank1 */ +#define FLASH_BANK2_END (0x080FFFFFUL) /*!< FLASH END address of bank2 */ +#define SRAM1_BASE (0x20000000UL) /*!< SRAM1(up to 96 KB) base address */ +#define SRAM2_BASE (0x10000000UL) /*!< SRAM2(32 KB) base address */ +#define PERIPH_BASE (0x40000000UL) /*!< Peripheral base address */ +#define FMC_BASE (0x60000000UL) /*!< FMC base address */ +#define QSPI_BASE (0x90000000UL) /*!< QUADSPI memories accessible over AHB base address */ + +#define FMC_R_BASE (0xA0000000UL) /*!< FMC control registers base address */ +#define QSPI_R_BASE (0xA0001000UL) /*!< QUADSPI control registers base address */ +#define SRAM1_BB_BASE (0x22000000UL) /*!< SRAM1(96 KB) base address in the bit-band region */ +#define PERIPH_BB_BASE (0x42000000UL) /*!< Peripheral base address in the bit-band region */ + +/* Legacy defines */ +#define SRAM_BASE SRAM1_BASE +#define SRAM_BB_BASE SRAM1_BB_BASE + +#define SRAM1_SIZE_MAX (0x00018000UL) /*!< maximum SRAM1 size (up to 96 KBytes) */ +#define SRAM2_SIZE (0x00008000UL) /*!< SRAM2 size (32 KBytes) */ + +#define FLASH_SIZE_DATA_REGISTER ((uint32_t)0x1FFF75E0) + +#define FLASH_SIZE (((((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0000FFFFU))== 0x0000FFFFU)) ? (0x400U << 10U) : \ + (((*((uint32_t *)FLASH_SIZE_DATA_REGISTER)) & (0x0000FFFFU)) << 10U)) + +/*!< Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL) + +#define FMC_BANK1 FMC_BASE +#define FMC_BANK1_1 FMC_BANK1 +#define FMC_BANK1_2 (FMC_BANK1 + 0x04000000UL) +#define FMC_BANK1_3 (FMC_BANK1 + 0x08000000UL) +#define FMC_BANK1_4 (FMC_BANK1 + 0x0C000000UL) +#define FMC_BANK3 (FMC_BASE + 0x20000000UL) + +/*!< APB1 peripherals */ +#define TIM2_BASE (APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (APB1PERIPH_BASE + 0x1400UL) +#define LCD_BASE (APB1PERIPH_BASE + 0x2400UL) +#define RTC_BASE (APB1PERIPH_BASE + 0x2800UL) +#define WWDG_BASE (APB1PERIPH_BASE + 0x2C00UL) +#define IWDG_BASE (APB1PERIPH_BASE + 0x3000UL) +#define SPI2_BASE (APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (APB1PERIPH_BASE + 0x3C00UL) +#define USART2_BASE (APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (APB1PERIPH_BASE + 0x5C00UL) +#define CAN1_BASE (APB1PERIPH_BASE + 0x6400UL) +#define PWR_BASE (APB1PERIPH_BASE + 0x7000UL) +#define DAC_BASE (APB1PERIPH_BASE + 0x7400UL) +#define DAC1_BASE (APB1PERIPH_BASE + 0x7400UL) +#define OPAMP_BASE (APB1PERIPH_BASE + 0x7800UL) +#define OPAMP1_BASE (APB1PERIPH_BASE + 0x7800UL) +#define OPAMP2_BASE (APB1PERIPH_BASE + 0x7810UL) +#define LPTIM1_BASE (APB1PERIPH_BASE + 0x7C00UL) +#define LPUART1_BASE (APB1PERIPH_BASE + 0x8000UL) +#define SWPMI1_BASE (APB1PERIPH_BASE + 0x8800UL) +#define LPTIM2_BASE (APB1PERIPH_BASE + 0x9400UL) + + +/*!< APB2 peripherals */ +#define SYSCFG_BASE (APB2PERIPH_BASE + 0x0000UL) +#define VREFBUF_BASE (APB2PERIPH_BASE + 0x0030UL) +#define COMP1_BASE (APB2PERIPH_BASE + 0x0200UL) +#define COMP2_BASE (APB2PERIPH_BASE + 0x0204UL) +#define EXTI_BASE (APB2PERIPH_BASE + 0x0400UL) +#define FIREWALL_BASE (APB2PERIPH_BASE + 0x1C00UL) +#define SDMMC1_BASE (APB2PERIPH_BASE + 0x2800UL) +#define TIM1_BASE (APB2PERIPH_BASE + 0x2C00UL) +#define SPI1_BASE (APB2PERIPH_BASE + 0x3000UL) +#define TIM8_BASE (APB2PERIPH_BASE + 0x3400UL) +#define USART1_BASE (APB2PERIPH_BASE + 0x3800UL) +#define TIM15_BASE (APB2PERIPH_BASE + 0x4000UL) +#define TIM16_BASE (APB2PERIPH_BASE + 0x4400UL) +#define TIM17_BASE (APB2PERIPH_BASE + 0x4800UL) +#define SAI1_BASE (APB2PERIPH_BASE + 0x5400UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x0004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x0024UL) +#define SAI2_BASE (APB2PERIPH_BASE + 0x5800UL) +#define SAI2_Block_A_BASE (SAI2_BASE + 0x0004UL) +#define SAI2_Block_B_BASE (SAI2_BASE + 0x0024UL) +#define DFSDM1_BASE (APB2PERIPH_BASE + 0x6000UL) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x0000UL) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x0020UL) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x0040UL) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x0060UL) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x0080UL) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0x00A0UL) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0x00C0UL) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0x00E0UL) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x0100UL) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x0180UL) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x0200UL) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x0280UL) + +/*!< AHB1 peripherals */ +#define DMA1_BASE (AHB1PERIPH_BASE) +#define DMA2_BASE (AHB1PERIPH_BASE + 0x0400UL) +#define RCC_BASE (AHB1PERIPH_BASE + 0x1000UL) +#define FLASH_R_BASE (AHB1PERIPH_BASE + 0x2000UL) +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000UL) +#define TSC_BASE (AHB1PERIPH_BASE + 0x4000UL) + + +#define DMA1_Channel1_BASE (DMA1_BASE + 0x0008UL) +#define DMA1_Channel2_BASE (DMA1_BASE + 0x001CUL) +#define DMA1_Channel3_BASE (DMA1_BASE + 0x0030UL) +#define DMA1_Channel4_BASE (DMA1_BASE + 0x0044UL) +#define DMA1_Channel5_BASE (DMA1_BASE + 0x0058UL) +#define DMA1_Channel6_BASE (DMA1_BASE + 0x006CUL) +#define DMA1_Channel7_BASE (DMA1_BASE + 0x0080UL) +#define DMA1_CSELR_BASE (DMA1_BASE + 0x00A8UL) + + +#define DMA2_Channel1_BASE (DMA2_BASE + 0x0008UL) +#define DMA2_Channel2_BASE (DMA2_BASE + 0x001CUL) +#define DMA2_Channel3_BASE (DMA2_BASE + 0x0030UL) +#define DMA2_Channel4_BASE (DMA2_BASE + 0x0044UL) +#define DMA2_Channel5_BASE (DMA2_BASE + 0x0058UL) +#define DMA2_Channel6_BASE (DMA2_BASE + 0x006CUL) +#define DMA2_Channel7_BASE (DMA2_BASE + 0x0080UL) +#define DMA2_CSELR_BASE (DMA2_BASE + 0x00A8UL) + + +/*!< AHB2 peripherals */ +#define GPIOA_BASE (AHB2PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (AHB2PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (AHB2PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (AHB2PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (AHB2PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (AHB2PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (AHB2PERIPH_BASE + 0x1C00UL) + +#define USBOTG_BASE (AHB2PERIPH_BASE + 0x08000000UL) + +#define ADC1_BASE (AHB2PERIPH_BASE + 0x08040000UL) +#define ADC2_BASE (AHB2PERIPH_BASE + 0x08040100UL) +#define ADC3_BASE (AHB2PERIPH_BASE + 0x08040200UL) +#define ADC123_COMMON_BASE (AHB2PERIPH_BASE + 0x08040300UL) + + +#define RNG_BASE (AHB2PERIPH_BASE + 0x08060800UL) + + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE (0xE0042000UL) + +/*!< USB registers base address */ +#define USB_OTG_FS_PERIPH_BASE (0x50000000UL) + +#define USB_OTG_GLOBAL_BASE (0x00000000UL) +#define USB_OTG_DEVICE_BASE (0x00000800UL) +#define USB_OTG_IN_ENDPOINT_BASE (0x00000900UL) +#define USB_OTG_OUT_ENDPOINT_BASE (0x00000B00UL) +#define USB_OTG_EP_REG_SIZE (0x00000020UL) +#define USB_OTG_HOST_BASE (0x00000400UL) +#define USB_OTG_HOST_PORT_BASE (0x00000440UL) +#define USB_OTG_HOST_CHANNEL_BASE (0x00000500UL) +#define USB_OTG_HOST_CHANNEL_SIZE (0x00000020UL) +#define USB_OTG_PCGCCTL_BASE (0x00000E00UL) +#define USB_OTG_FIFO_BASE (0x00001000UL) +#define USB_OTG_FIFO_SIZE (0x00001000UL) + + +#define PACKAGE_BASE (0x1FFF7500UL) /*!< Package data register base address */ +#define UID_BASE (0x1FFF7590UL) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE (0x1FFF75E0UL) /*!< Flash size data register base address */ +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define LCD ((LCD_TypeDef *) LCD_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG ((WWDG_TypeDef *) WWDG_BASE) +#define IWDG ((IWDG_TypeDef *) IWDG_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define CAN ((CAN_TypeDef *) CAN1_BASE) +#define CAN1 ((CAN_TypeDef *) CAN1_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC ((DAC_TypeDef *) DAC1_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) +#define OPAMP12_COMMON ((OPAMP_Common_TypeDef *) OPAMP1_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define FIREWALL ((FIREWALL_TypeDef *) FIREWALL_BASE) +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI2 ((SAI_TypeDef *) SAI2_BASE) +#define SAI2_Block_A ((SAI_Block_TypeDef *)SAI2_Block_A_BASE) +#define SAI2_Block_B ((SAI_Block_TypeDef *)SAI2_Block_B_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +/* Aliases to keep compatibility after DFSDM renaming */ +#define DFSDM_Channel0 DFSDM1_Channel0 +#define DFSDM_Channel1 DFSDM1_Channel1 +#define DFSDM_Channel2 DFSDM1_Channel2 +#define DFSDM_Channel3 DFSDM1_Channel3 +#define DFSDM_Channel4 DFSDM1_Channel4 +#define DFSDM_Channel5 DFSDM1_Channel5 +#define DFSDM_Channel6 DFSDM1_Channel6 +#define DFSDM_Channel7 DFSDM1_Channel7 +#define DFSDM_Filter0 DFSDM1_Filter0 +#define DFSDM_Filter1 DFSDM1_Filter1 +#define DFSDM_Filter2 DFSDM1_Filter2 +#define DFSDM_Filter3 DFSDM1_Filter3 +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) +#define TSC ((TSC_TypeDef *) TSC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC123_COMMON ((ADC_Common_TypeDef *) ADC123_COMMON_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) + + +#define DMA1_Channel1 ((DMA_Channel_TypeDef *) DMA1_Channel1_BASE) +#define DMA1_Channel2 ((DMA_Channel_TypeDef *) DMA1_Channel2_BASE) +#define DMA1_Channel3 ((DMA_Channel_TypeDef *) DMA1_Channel3_BASE) +#define DMA1_Channel4 ((DMA_Channel_TypeDef *) DMA1_Channel4_BASE) +#define DMA1_Channel5 ((DMA_Channel_TypeDef *) DMA1_Channel5_BASE) +#define DMA1_Channel6 ((DMA_Channel_TypeDef *) DMA1_Channel6_BASE) +#define DMA1_Channel7 ((DMA_Channel_TypeDef *) DMA1_Channel7_BASE) +#define DMA1_CSELR ((DMA_Request_TypeDef *) DMA1_CSELR_BASE) + + +#define DMA2_Channel1 ((DMA_Channel_TypeDef *) DMA2_Channel1_BASE) +#define DMA2_Channel2 ((DMA_Channel_TypeDef *) DMA2_Channel2_BASE) +#define DMA2_Channel3 ((DMA_Channel_TypeDef *) DMA2_Channel3_BASE) +#define DMA2_Channel4 ((DMA_Channel_TypeDef *) DMA2_Channel4_BASE) +#define DMA2_Channel5 ((DMA_Channel_TypeDef *) DMA2_Channel5_BASE) +#define DMA2_Channel6 ((DMA_Channel_TypeDef *) DMA2_Channel6_BASE) +#define DMA2_Channel7 ((DMA_Channel_TypeDef *) DMA2_Channel7_BASE) +#define DMA2_CSELR ((DMA_Request_TypeDef *) DMA2_CSELR_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) + +#define QUADSPI ((QUADSPI_TypeDef *) QSPI_R_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define USB_OTG_FS ((USB_OTG_GlobalTypeDef *) USB_OTG_FS_PERIPH_BASE) +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + +/** @addtogroup Hardware_Constant_Definition + * @{ + */ +#define LSI_STARTUP_TIME 130U /*!< LSI Maximum startup time in us */ + +/** + * @} + */ + +/** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ + +/* + * @brief Specific device feature definitions (not present on all devices in the STM32L4 series) + */ +#define ADC_MULTIMODE_SUPPORT /*!< ADC feature available only on specific devices: multimode available on devices with several ADC instances */ + +/******************** Bit definition for ADC_ISR register *******************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC ready flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC group regular end of sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC group regular end of unitary conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC group regular end of sequence conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC group regular overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC group injected end of unitary conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC group injected end of sequence conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC group injected contexts queue overflow flag */ + +/******************** Bit definition for ADC_IER register *******************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC ready interrupt */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC group regular end of sampling interrupt */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC group regular end of unitary conversion interrupt */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC group regular end of sequence conversions interrupt */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC group regular overrun interrupt */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC group injected end of unitary conversion interrupt */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC group injected end of sequence conversions interrupt */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC analog watchdog 1 interrupt */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC analog watchdog 2 interrupt */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC analog watchdog 3 interrupt */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC group injected contexts queue overflow interrupt */ + +/* Legacy defines */ +#define ADC_IER_ADRDY (ADC_IER_ADRDYIE) +#define ADC_IER_EOSMP (ADC_IER_EOSMPIE) +#define ADC_IER_EOC (ADC_IER_EOCIE) +#define ADC_IER_EOS (ADC_IER_EOSIE) +#define ADC_IER_OVR (ADC_IER_OVRIE) +#define ADC_IER_JEOC (ADC_IER_JEOCIE) +#define ADC_IER_JEOS (ADC_IER_JEOSIE) +#define ADC_IER_AWD1 (ADC_IER_AWD1IE) +#define ADC_IER_AWD2 (ADC_IER_AWD2IE) +#define ADC_IER_AWD3 (ADC_IER_AWD3IE) +#define ADC_IER_JQOVF (ADC_IER_JQOVFIE) + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC enable */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC disable */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC group regular conversion start */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC group injected conversion start */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC group regular conversion stop */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC group injected conversion stop */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC voltage regulator enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC deep power down enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC differential mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC calibration */ + +/******************** Bit definition for ADC_CFGR register ******************/ +#define ADC_CFGR_DMAEN_Pos (0U) +#define ADC_CFGR_DMAEN_Msk (0x1UL << ADC_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMAEN ADC_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC_CFGR_DMACFG_Pos (1U) +#define ADC_CFGR_DMACFG_Msk (0x1UL << ADC_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC_CFGR_DMACFG ADC_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC_CFGR_RES_Pos (3U) +#define ADC_CFGR_RES_Msk (0x3UL << ADC_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_ALIGN_Pos (5U) +#define ADC_CFGR_ALIGN_Msk (0x1UL << ADC_CFGR_ALIGN_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_ALIGN ADC_CFGR_ALIGN_Msk /*!< ADC data alignment */ + +#define ADC_CFGR_EXTSEL_Pos (6U) +#define ADC_CFGR_EXTSEL_Msk (0xFUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003C0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC group regular external trigger source */ +#define ADC_CFGR_EXTSEL_0 (0x1UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_1 (0x2UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_2 (0x4UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_3 (0x8UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC group regular external trigger polarity */ +#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC group regular overrun configuration */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC group regular continuous conversion mode */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC low power auto wait */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC group regular sequencer discontinuous mode */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC group regular sequencer discontinuous number of ranks */ +#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC group injected sequencer discontinuous mode */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC group injected contexts queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< ADC analog watchdog 1 monitoring a single channel or all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group regular */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC analog watchdog 1 enable on scope ADC group injected */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC group injected automatic trigger mode */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC analog watchdog 1 monitored channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC group injected contexts queue disable */ + +/******************** Bit definition for ADC_CFGR2 register *****************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC oversampler enable on scope ADC group regular */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC oversampler enable on scope ADC group injected */ + +#define ADC_CFGR2_OVSR_Pos (2U) +#define ADC_CFGR2_OVSR_Msk (0x7UL << ADC_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC_CFGR2_OVSR_0 (0x1UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC_CFGR2_OVSR_1 (0x2UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC_CFGR2_OVSR_2 (0x4UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC oversampling discontinuous mode (triggered mode) for ADC group regular */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC oversampling mode managing interlaced conversions of ADC group regular and group injected */ + +/******************** Bit definition for ADC_SMPR1 register *****************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC channel 0 sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC channel 1 sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC channel 2 sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC channel 3 sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC channel 4 sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC channel 5 sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC channel 6 sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC channel 7 sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC channel 8 sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC channel 9 sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_SMPR2 register *****************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC channel 10 sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC channel 11 sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC channel 12 sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC channel 13 sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC channel 14 sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC channel 15 sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC channel 16 sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC channel 17 sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC channel 18 sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_TR1 register *******************/ +#define ADC_TR1_LT1_Pos (0U) +#define ADC_TR1_LT1_Msk (0xFFFUL << ADC_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC_TR1_LT1 ADC_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ +#define ADC_TR1_LT1_0 (0x001UL << ADC_TR1_LT1_Pos) /*!< 0x00000001 */ +#define ADC_TR1_LT1_1 (0x002UL << ADC_TR1_LT1_Pos) /*!< 0x00000002 */ +#define ADC_TR1_LT1_2 (0x004UL << ADC_TR1_LT1_Pos) /*!< 0x00000004 */ +#define ADC_TR1_LT1_3 (0x008UL << ADC_TR1_LT1_Pos) /*!< 0x00000008 */ +#define ADC_TR1_LT1_4 (0x010UL << ADC_TR1_LT1_Pos) /*!< 0x00000010 */ +#define ADC_TR1_LT1_5 (0x020UL << ADC_TR1_LT1_Pos) /*!< 0x00000020 */ +#define ADC_TR1_LT1_6 (0x040UL << ADC_TR1_LT1_Pos) /*!< 0x00000040 */ +#define ADC_TR1_LT1_7 (0x080UL << ADC_TR1_LT1_Pos) /*!< 0x00000080 */ +#define ADC_TR1_LT1_8 (0x100UL << ADC_TR1_LT1_Pos) /*!< 0x00000100 */ +#define ADC_TR1_LT1_9 (0x200UL << ADC_TR1_LT1_Pos) /*!< 0x00000200 */ +#define ADC_TR1_LT1_10 (0x400UL << ADC_TR1_LT1_Pos) /*!< 0x00000400 */ +#define ADC_TR1_LT1_11 (0x800UL << ADC_TR1_LT1_Pos) /*!< 0x00000800 */ + +#define ADC_TR1_HT1_Pos (16U) +#define ADC_TR1_HT1_Msk (0xFFFUL << ADC_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC_TR1_HT1 ADC_TR1_HT1_Msk /*!< ADC Analog watchdog 1 threshold high */ +#define ADC_TR1_HT1_0 (0x001UL << ADC_TR1_HT1_Pos) /*!< 0x00010000 */ +#define ADC_TR1_HT1_1 (0x002UL << ADC_TR1_HT1_Pos) /*!< 0x00020000 */ +#define ADC_TR1_HT1_2 (0x004UL << ADC_TR1_HT1_Pos) /*!< 0x00040000 */ +#define ADC_TR1_HT1_3 (0x008UL << ADC_TR1_HT1_Pos) /*!< 0x00080000 */ +#define ADC_TR1_HT1_4 (0x010UL << ADC_TR1_HT1_Pos) /*!< 0x00100000 */ +#define ADC_TR1_HT1_5 (0x020UL << ADC_TR1_HT1_Pos) /*!< 0x00200000 */ +#define ADC_TR1_HT1_6 (0x040UL << ADC_TR1_HT1_Pos) /*!< 0x00400000 */ +#define ADC_TR1_HT1_7 (0x080UL << ADC_TR1_HT1_Pos) /*!< 0x00800000 */ +#define ADC_TR1_HT1_8 (0x100UL << ADC_TR1_HT1_Pos) /*!< 0x01000000 */ +#define ADC_TR1_HT1_9 (0x200UL << ADC_TR1_HT1_Pos) /*!< 0x02000000 */ +#define ADC_TR1_HT1_10 (0x400UL << ADC_TR1_HT1_Pos) /*!< 0x04000000 */ +#define ADC_TR1_HT1_11 (0x800UL << ADC_TR1_HT1_Pos) /*!< 0x08000000 */ + +/******************** Bit definition for ADC_TR2 register *******************/ +#define ADC_TR2_LT2_Pos (0U) +#define ADC_TR2_LT2_Msk (0xFFUL << ADC_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC_TR2_LT2 ADC_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ +#define ADC_TR2_LT2_0 (0x01UL << ADC_TR2_LT2_Pos) /*!< 0x00000001 */ +#define ADC_TR2_LT2_1 (0x02UL << ADC_TR2_LT2_Pos) /*!< 0x00000002 */ +#define ADC_TR2_LT2_2 (0x04UL << ADC_TR2_LT2_Pos) /*!< 0x00000004 */ +#define ADC_TR2_LT2_3 (0x08UL << ADC_TR2_LT2_Pos) /*!< 0x00000008 */ +#define ADC_TR2_LT2_4 (0x10UL << ADC_TR2_LT2_Pos) /*!< 0x00000010 */ +#define ADC_TR2_LT2_5 (0x20UL << ADC_TR2_LT2_Pos) /*!< 0x00000020 */ +#define ADC_TR2_LT2_6 (0x40UL << ADC_TR2_LT2_Pos) /*!< 0x00000040 */ +#define ADC_TR2_LT2_7 (0x80UL << ADC_TR2_LT2_Pos) /*!< 0x00000080 */ + +#define ADC_TR2_HT2_Pos (16U) +#define ADC_TR2_HT2_Msk (0xFFUL << ADC_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC_TR2_HT2 ADC_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ +#define ADC_TR2_HT2_0 (0x01UL << ADC_TR2_HT2_Pos) /*!< 0x00010000 */ +#define ADC_TR2_HT2_1 (0x02UL << ADC_TR2_HT2_Pos) /*!< 0x00020000 */ +#define ADC_TR2_HT2_2 (0x04UL << ADC_TR2_HT2_Pos) /*!< 0x00040000 */ +#define ADC_TR2_HT2_3 (0x08UL << ADC_TR2_HT2_Pos) /*!< 0x00080000 */ +#define ADC_TR2_HT2_4 (0x10UL << ADC_TR2_HT2_Pos) /*!< 0x00100000 */ +#define ADC_TR2_HT2_5 (0x20UL << ADC_TR2_HT2_Pos) /*!< 0x00200000 */ +#define ADC_TR2_HT2_6 (0x40UL << ADC_TR2_HT2_Pos) /*!< 0x00400000 */ +#define ADC_TR2_HT2_7 (0x80UL << ADC_TR2_HT2_Pos) /*!< 0x00800000 */ + +/******************** Bit definition for ADC_TR3 register *******************/ +#define ADC_TR3_LT3_Pos (0U) +#define ADC_TR3_LT3_Msk (0xFFUL << ADC_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC_TR3_LT3 ADC_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ +#define ADC_TR3_LT3_0 (0x01UL << ADC_TR3_LT3_Pos) /*!< 0x00000001 */ +#define ADC_TR3_LT3_1 (0x02UL << ADC_TR3_LT3_Pos) /*!< 0x00000002 */ +#define ADC_TR3_LT3_2 (0x04UL << ADC_TR3_LT3_Pos) /*!< 0x00000004 */ +#define ADC_TR3_LT3_3 (0x08UL << ADC_TR3_LT3_Pos) /*!< 0x00000008 */ +#define ADC_TR3_LT3_4 (0x10UL << ADC_TR3_LT3_Pos) /*!< 0x00000010 */ +#define ADC_TR3_LT3_5 (0x20UL << ADC_TR3_LT3_Pos) /*!< 0x00000020 */ +#define ADC_TR3_LT3_6 (0x40UL << ADC_TR3_LT3_Pos) /*!< 0x00000040 */ +#define ADC_TR3_LT3_7 (0x80UL << ADC_TR3_LT3_Pos) /*!< 0x00000080 */ + +#define ADC_TR3_HT3_Pos (16U) +#define ADC_TR3_HT3_Msk (0xFFUL << ADC_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC_TR3_HT3 ADC_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ +#define ADC_TR3_HT3_0 (0x01UL << ADC_TR3_HT3_Pos) /*!< 0x00010000 */ +#define ADC_TR3_HT3_1 (0x02UL << ADC_TR3_HT3_Pos) /*!< 0x00020000 */ +#define ADC_TR3_HT3_2 (0x04UL << ADC_TR3_HT3_Pos) /*!< 0x00040000 */ +#define ADC_TR3_HT3_3 (0x08UL << ADC_TR3_HT3_Pos) /*!< 0x00080000 */ +#define ADC_TR3_HT3_4 (0x10UL << ADC_TR3_HT3_Pos) /*!< 0x00100000 */ +#define ADC_TR3_HT3_5 (0x20UL << ADC_TR3_HT3_Pos) /*!< 0x00200000 */ +#define ADC_TR3_HT3_6 (0x40UL << ADC_TR3_HT3_Pos) /*!< 0x00400000 */ +#define ADC_TR3_HT3_7 (0x80UL << ADC_TR3_HT3_Pos) /*!< 0x00800000 */ + +/******************** Bit definition for ADC_SQR1 register ******************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC group regular sequencer scan length */ +#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC group regular sequencer rank 1 */ +#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC group regular sequencer rank 2 */ +#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC group regular sequencer rank 3 */ +#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10UL << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC group regular sequencer rank 4 */ +#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ******************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC group regular sequencer rank 5 */ +#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC group regular sequencer rank 6 */ +#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC group regular sequencer rank 7 */ +#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC group regular sequencer rank 8 */ +#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC group regular sequencer rank 9 */ +#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ******************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC group regular sequencer rank 10 */ +#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC group regular sequencer rank 11 */ +#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC group regular sequencer rank 12 */ +#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC group regular sequencer rank 13 */ +#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC group regular sequencer rank 14 */ +#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ******************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC group regular sequencer rank 15 */ +#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC group regular sequencer rank 16 */ +#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ + +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFUL << ADC_DR_RDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC group regular conversion data */ +#define ADC_DR_RDATA_0 (0x0001UL << ADC_DR_RDATA_Pos) /*!< 0x00000001 */ +#define ADC_DR_RDATA_1 (0x0002UL << ADC_DR_RDATA_Pos) /*!< 0x00000002 */ +#define ADC_DR_RDATA_2 (0x0004UL << ADC_DR_RDATA_Pos) /*!< 0x00000004 */ +#define ADC_DR_RDATA_3 (0x0008UL << ADC_DR_RDATA_Pos) /*!< 0x00000008 */ +#define ADC_DR_RDATA_4 (0x0010UL << ADC_DR_RDATA_Pos) /*!< 0x00000010 */ +#define ADC_DR_RDATA_5 (0x0020UL << ADC_DR_RDATA_Pos) /*!< 0x00000020 */ +#define ADC_DR_RDATA_6 (0x0040UL << ADC_DR_RDATA_Pos) /*!< 0x00000040 */ +#define ADC_DR_RDATA_7 (0x0080UL << ADC_DR_RDATA_Pos) /*!< 0x00000080 */ +#define ADC_DR_RDATA_8 (0x0100UL << ADC_DR_RDATA_Pos) /*!< 0x00000100 */ +#define ADC_DR_RDATA_9 (0x0200UL << ADC_DR_RDATA_Pos) /*!< 0x00000200 */ +#define ADC_DR_RDATA_10 (0x0400UL << ADC_DR_RDATA_Pos) /*!< 0x00000400 */ +#define ADC_DR_RDATA_11 (0x0800UL << ADC_DR_RDATA_Pos) /*!< 0x00000800 */ +#define ADC_DR_RDATA_12 (0x1000UL << ADC_DR_RDATA_Pos) /*!< 0x00001000 */ +#define ADC_DR_RDATA_13 (0x2000UL << ADC_DR_RDATA_Pos) /*!< 0x00002000 */ +#define ADC_DR_RDATA_14 (0x4000UL << ADC_DR_RDATA_Pos) /*!< 0x00004000 */ +#define ADC_DR_RDATA_15 (0x8000UL << ADC_DR_RDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JSQR register ******************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC group injected sequencer scan length */ +#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0xFUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000003C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC group injected external trigger source */ +#define ADC_JSQR_JEXTSEL_0 (0x1UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x2UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x4UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x8UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ + +#define ADC_JSQR_JEXTEN_Pos (6U) +#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x000000C0 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC group injected external trigger polarity */ +#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000040 */ +#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ + +#define ADC_JSQR_JSQ1_Pos (8U) +#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001F00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC group injected sequencer rank 1 */ +#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000100 */ +#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ + +#define ADC_JSQR_JSQ2_Pos (14U) +#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x0007C000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC group injected sequencer rank 2 */ +#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00004000 */ +#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ + +#define ADC_JSQR_JSQ3_Pos (20U) +#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x01F00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC group injected sequencer rank 3 */ +#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00100000 */ +#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ + +#define ADC_JSQR_JSQ4_Pos (26U) +#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0x7C000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC group injected sequencer rank 4 */ +#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x04000000 */ +#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ + +/******************** Bit definition for ADC_OFR1 register ******************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0xFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC offset number 1 offset level */ +#define ADC_OFR1_OFFSET1_0 (0x001UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x002UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x004UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x008UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x010UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x020UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x040UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x080UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x100UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x200UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x400UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x800UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC offset number 1 channel selection */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_OFFSET1_EN_Pos (31U) +#define ADC_OFR1_OFFSET1_EN_Msk (0x1UL << ADC_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_OFFSET1_EN ADC_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ******************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0xFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC offset number 2 offset level */ +#define ADC_OFR2_OFFSET2_0 (0x001UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x002UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x004UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x008UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x010UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x020UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x040UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x080UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x100UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x200UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x400UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x800UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC offset number 2 channel selection */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_OFFSET2_EN_Pos (31U) +#define ADC_OFR2_OFFSET2_EN_Msk (0x1UL << ADC_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_OFFSET2_EN ADC_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ******************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0xFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC offset number 3 offset level */ +#define ADC_OFR3_OFFSET3_0 (0x001UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x002UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x004UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x008UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x010UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x020UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x040UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x080UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x100UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x200UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x400UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x800UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC offset number 3 channel selection */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_OFFSET3_EN_Pos (31U) +#define ADC_OFR3_OFFSET3_EN_Msk (0x1UL << ADC_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_OFFSET3_EN ADC_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ******************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0xFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC offset number 4 offset level */ +#define ADC_OFR4_OFFSET4_0 (0x001UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x002UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x004UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x008UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x010UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x020UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x040UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x080UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x100UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x200UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x400UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x800UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC offset number 4 channel selection */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_OFFSET4_EN_Pos (31U) +#define ADC_OFR4_OFFSET4_EN_Msk (0x1UL << ADC_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_OFFSET4_EN ADC_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ******************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC group injected sequencer rank 1 conversion data */ +#define ADC_JDR1_JDATA_0 (0x0001UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x0002UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x0004UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x0008UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x0010UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x0020UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x0040UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x0080UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x0100UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x0200UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x0400UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x0800UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x1000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x2000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x4000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x8000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR2 register ******************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC group injected sequencer rank 2 conversion data */ +#define ADC_JDR2_JDATA_0 (0x0001UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x0002UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x0004UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x0008UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x0010UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x0020UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x0040UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x0080UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x0100UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x0200UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x0400UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x0800UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x1000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x2000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x4000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x8000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR3 register ******************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC group injected sequencer rank 3 conversion data */ +#define ADC_JDR3_JDATA_0 (0x0001UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x0002UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x0004UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x0008UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x0010UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x0020UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x0040UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x0080UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x0100UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x0200UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x0400UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x0800UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x1000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x2000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x4000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x8000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_JDR4 register ******************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0x0000FFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC group injected sequencer rank 4 conversion data */ +#define ADC_JDR4_JDATA_0 (0x0001UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x0002UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x0004UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x0008UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x0010UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x0020UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x0040UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x0080UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x0100UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x0200UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x0400UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x0800UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x1000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x2000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x4000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x8000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ + +/******************** Bit definition for ADC_AWD2CR register ****************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0x7FFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x0007FFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC analog watchdog 2 monitored channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_AWD3CR register ****************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0x7FFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x0007FFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC analog watchdog 3 monitored channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_DIFSEL register ****************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0x7FFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x0007FFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC channel differential or single-ended mode */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ + +/******************** Bit definition for ADC_CALFACT register ***************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x0000007F */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factor in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x01UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x02UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x04UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x08UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x10UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x20UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x40UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ + +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x007F0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factor in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x01UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x02UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x04UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x08UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x10UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x20UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x40UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register *******************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< ADC multimode master ready flag */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< ADC multimode master group regular end of sampling flag */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< ADC multimode master group regular end of unitary conversion flag */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< ADC multimode master group regular end of sequence conversions flag */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< ADC multimode master group regular overrun flag */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< ADC multimode master group injected end of unitary conversion flag */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< ADC multimode master group injected end of sequence conversions flag */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< ADC multimode master analog watchdog 1 flag */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< ADC multimode master analog watchdog 2 flag */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< ADC multimode master analog watchdog 3 flag */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< ADC multimode master group injected contexts queue overflow flag */ + +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< ADC multimode slave ready flag */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< ADC multimode slave group regular end of sampling flag */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< ADC multimode slave group regular end of unitary conversion flag */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< ADC multimode slave group regular end of sequence conversions flag */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< ADC multimode slave group regular overrun flag */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< ADC multimode slave group injected end of unitary conversion flag */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< ADC multimode slave group injected end of sequence conversions flag */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< ADC multimode slave analog watchdog 1 flag */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< ADC multimode slave analog watchdog 2 flag */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< ADC multimode slave analog watchdog 3 flag */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< ADC multimode slave group injected contexts queue overflow flag */ + +/******************** Bit definition for ADC_CCR register *******************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< ADC multimode mode selection */ +#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< ADC multimode delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + +#define ADC_CCR_DMACFG_Pos (13U) +#define ADC_CCR_DMACFG_Msk (0x1UL << ADC_CCR_DMACFG_Pos) /*!< 0x00002000 */ +#define ADC_CCR_DMACFG ADC_CCR_DMACFG_Msk /*!< ADC multimode DMA transfer configuration */ + +#define ADC_CCR_MDMA_Pos (14U) +#define ADC_CCR_MDMA_Msk (0x3UL << ADC_CCR_MDMA_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_MDMA ADC_CCR_MDMA_Msk /*!< ADC multimode DMA transfer enable */ +#define ADC_CCR_MDMA_0 (0x1UL << ADC_CCR_MDMA_Pos) /*!< 0x00004000 */ +#define ADC_CCR_MDMA_1 (0x2UL << ADC_CCR_MDMA_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC common clock source and prescaler (prescaler only for clock source synchronous) */ +#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC common clock prescaler, only for clock source asynchronous */ +#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< ADC internal path to VrefInt enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1UL << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< ADC internal path to temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1UL << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< ADC internal path to battery voltage enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ +#define ADC_CDR_RDATA_MST_0 (0x0001UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000001 */ +#define ADC_CDR_RDATA_MST_1 (0x0002UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000002 */ +#define ADC_CDR_RDATA_MST_2 (0x0004UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000004 */ +#define ADC_CDR_RDATA_MST_3 (0x0008UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000008 */ +#define ADC_CDR_RDATA_MST_4 (0x0010UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000010 */ +#define ADC_CDR_RDATA_MST_5 (0x0020UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000020 */ +#define ADC_CDR_RDATA_MST_6 (0x0040UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000040 */ +#define ADC_CDR_RDATA_MST_7 (0x0080UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000080 */ +#define ADC_CDR_RDATA_MST_8 (0x0100UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000100 */ +#define ADC_CDR_RDATA_MST_9 (0x0200UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000200 */ +#define ADC_CDR_RDATA_MST_10 (0x0400UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000400 */ +#define ADC_CDR_RDATA_MST_11 (0x0800UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00000800 */ +#define ADC_CDR_RDATA_MST_12 (0x1000UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00001000 */ +#define ADC_CDR_RDATA_MST_13 (0x2000UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00002000 */ +#define ADC_CDR_RDATA_MST_14 (0x4000UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00004000 */ +#define ADC_CDR_RDATA_MST_15 (0x8000UL << ADC_CDR_RDATA_MST_Pos) /*!< 0x00008000 */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ +#define ADC_CDR_RDATA_SLV_0 (0x0001UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CDR_RDATA_SLV_1 (0x0002UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CDR_RDATA_SLV_2 (0x0004UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CDR_RDATA_SLV_3 (0x0008UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CDR_RDATA_SLV_4 (0x0010UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CDR_RDATA_SLV_5 (0x0020UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CDR_RDATA_SLV_6 (0x0040UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CDR_RDATA_SLV_7 (0x0080UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CDR_RDATA_SLV_8 (0x0100UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CDR_RDATA_SLV_9 (0x0200UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CDR_RDATA_SLV_10 (0x0400UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CDR_RDATA_SLV_11 (0x0800UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x08000000 */ +#define ADC_CDR_RDATA_SLV_12 (0x1000UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x10000000 */ +#define ADC_CDR_RDATA_SLV_13 (0x2000UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x20000000 */ +#define ADC_CDR_RDATA_SLV_14 (0x4000UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x40000000 */ +#define ADC_CDR_RDATA_SLV_15 (0x8000UL << ADC_CDR_RDATA_SLV_Pos) /*!< 0x80000000 */ + +/******************************************************************************/ +/* */ +/* Controller Area Network */ +/* */ +/******************************************************************************/ +/*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return result; +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/Drivers/CMSIS/Include/cmsis_armclang.h b/Drivers/CMSIS/Include/cmsis_armclang.h new file mode 100644 index 0000000..e917f35 --- /dev/null +++ b/Drivers/CMSIS/Include/cmsis_armclang.h @@ -0,0 +1,1444 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.2.0 + * @date 08. May 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +#ifndef __ARM_COMPAT_H +#include /* Compatibility header for Arm Compiler 5 intrinsics */ +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section("RESET"))) +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); see arm_compat.h */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); see arm_compat.h */ + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +#define __SADD8 __builtin_arm_sadd8 +#define __QADD8 __builtin_arm_qadd8 +#define __SHADD8 __builtin_arm_shadd8 +#define __UADD8 __builtin_arm_uadd8 +#define __UQADD8 __builtin_arm_uqadd8 +#define __UHADD8 __builtin_arm_uhadd8 +#define __SSUB8 __builtin_arm_ssub8 +#define __QSUB8 __builtin_arm_qsub8 +#define __SHSUB8 __builtin_arm_shsub8 +#define __USUB8 __builtin_arm_usub8 +#define __UQSUB8 __builtin_arm_uqsub8 +#define __UHSUB8 __builtin_arm_uhsub8 +#define __SADD16 __builtin_arm_sadd16 +#define __QADD16 __builtin_arm_qadd16 +#define __SHADD16 __builtin_arm_shadd16 +#define __UADD16 __builtin_arm_uadd16 +#define __UQADD16 __builtin_arm_uqadd16 +#define __UHADD16 __builtin_arm_uhadd16 +#define __SSUB16 __builtin_arm_ssub16 +#define __QSUB16 __builtin_arm_qsub16 +#define __SHSUB16 __builtin_arm_shsub16 +#define __USUB16 __builtin_arm_usub16 +#define __UQSUB16 __builtin_arm_uqsub16 +#define __UHSUB16 __builtin_arm_uhsub16 +#define __SASX __builtin_arm_sasx +#define __QASX __builtin_arm_qasx +#define __SHASX __builtin_arm_shasx +#define __UASX __builtin_arm_uasx +#define __UQASX __builtin_arm_uqasx +#define __UHASX __builtin_arm_uhasx +#define __SSAX __builtin_arm_ssax +#define __QSAX __builtin_arm_qsax +#define __SHSAX __builtin_arm_shsax +#define __USAX __builtin_arm_usax +#define __UQSAX __builtin_arm_uqsax +#define __UHSAX __builtin_arm_uhsax +#define __USAD8 __builtin_arm_usad8 +#define __USADA8 __builtin_arm_usada8 +#define __SSAT16 __builtin_arm_ssat16 +#define __USAT16 __builtin_arm_usat16 +#define __UXTB16 __builtin_arm_uxtb16 +#define __UXTAB16 __builtin_arm_uxtab16 +#define __SXTB16 __builtin_arm_sxtb16 +#define __SXTAB16 __builtin_arm_sxtab16 +#define __SMUAD __builtin_arm_smuad +#define __SMUADX __builtin_arm_smuadx +#define __SMLAD __builtin_arm_smlad +#define __SMLADX __builtin_arm_smladx +#define __SMLALD __builtin_arm_smlald +#define __SMLALDX __builtin_arm_smlaldx +#define __SMUSD __builtin_arm_smusd +#define __SMUSDX __builtin_arm_smusdx +#define __SMLSD __builtin_arm_smlsd +#define __SMLSDX __builtin_arm_smlsdx +#define __SMLSLD __builtin_arm_smlsld +#define __SMLSLDX __builtin_arm_smlsldx +#define __SEL __builtin_arm_sel +#define __QADD __builtin_arm_qadd +#define __QSUB __builtin_arm_qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/Drivers/CMSIS/Include/cmsis_armclang_ltm.h b/Drivers/CMSIS/Include/cmsis_armclang_ltm.h new file mode 100644 index 0000000..feec324 --- /dev/null +++ b/Drivers/CMSIS/Include/cmsis_armclang_ltm.h @@ -0,0 +1,1891 @@ +/**************************************************************************//** + * @file cmsis_armclang_ltm.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V1.2.0 + * @date 08. May 2019 + ******************************************************************************/ +/* + * Copyright (c) 2018-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +#ifndef __ARM_COMPAT_H +#include /* Compatibility header for Arm Compiler 5 intrinsics */ +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section("RESET"))) +#endif + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); see arm_compat.h */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); see arm_compat.h */ + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq /* see arm_compat.h */ + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq /* see arm_compat.h */ + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/Drivers/CMSIS/Include/cmsis_compiler.h b/Drivers/CMSIS/Include/cmsis_compiler.h new file mode 100644 index 0000000..adbf296 --- /dev/null +++ b/Drivers/CMSIS/Include/cmsis_compiler.h @@ -0,0 +1,283 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.1.0 + * @date 09. October 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6.6 LTM (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) + #include "cmsis_armclang_ltm.h" + + /* + * Arm Compiler above 6.10.1 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) + #include "cmsis_armclang.h" + + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #define __RESTRICT __restrict + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/Drivers/CMSIS/Include/cmsis_gcc.h b/Drivers/CMSIS/Include/cmsis_gcc.h new file mode 100644 index 0000000..3ddcc58 --- /dev/null +++ b/Drivers/CMSIS/Include/cmsis_gcc.h @@ -0,0 +1,2168 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.2.0 + * @date 08. May 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section(".vectors"))) +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ + __extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#if 0 +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) +#endif + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ diff --git a/Drivers/CMSIS/Include/cmsis_iccarm.h b/Drivers/CMSIS/Include/cmsis_iccarm.h new file mode 100644 index 0000000..12d68fd --- /dev/null +++ b/Drivers/CMSIS/Include/cmsis_iccarm.h @@ -0,0 +1,964 @@ +/**************************************************************************//** + * @file cmsis_iccarm.h + * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file + * @version V5.1.0 + * @date 08. May 2019 + ******************************************************************************/ + +//------------------------------------------------------------------------------ +// +// Copyright (c) 2017-2019 IAR Systems +// Copyright (c) 2017-2019 Arm Limited. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License") +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------ + + +#ifndef __CMSIS_ICCARM_H__ +#define __CMSIS_ICCARM_H__ + +#ifndef __ICCARM__ + #error This file should only be compiled by ICCARM +#endif + +#pragma system_include + +#define __IAR_FT _Pragma("inline=forced") __intrinsic + +#if (__VER__ >= 8000000) + #define __ICCARM_V8 1 +#else + #define __ICCARM_V8 0 +#endif + +#ifndef __ALIGNED + #if __ICCARM_V8 + #define __ALIGNED(x) __attribute__((aligned(x))) + #elif (__VER__ >= 7080000) + /* Needs IAR language extensions */ + #define __ALIGNED(x) __attribute__((aligned(x))) + #else + #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. + #define __ALIGNED(x) + #endif +#endif + + +/* Define compiler macros for CPU architecture, used in CMSIS 5. + */ +#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__ +/* Macros already defined */ +#else + #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M' + #if __ARM_ARCH == 6 + #define __ARM_ARCH_6M__ 1 + #elif __ARM_ARCH == 7 + #if __ARM_FEATURE_DSP + #define __ARM_ARCH_7EM__ 1 + #else + #define __ARM_ARCH_7M__ 1 + #endif + #endif /* __ARM_ARCH */ + #endif /* __ARM_ARCH_PROFILE == 'M' */ +#endif + +/* Alternativ core deduction for older ICCARM's */ +#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \ + !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__) + #if defined(__ARM6M__) && (__CORE__ == __ARM6M__) + #define __ARM_ARCH_6M__ 1 + #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__) + #define __ARM_ARCH_7M__ 1 + #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__) + #define __ARM_ARCH_7EM__ 1 + #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__) + #define __ARM_ARCH_8M_BASE__ 1 + #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__) + #define __ARM_ARCH_8M_MAIN__ 1 + #else + #error "Unknown target." + #endif +#endif + + + +#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1 + #define __IAR_M0_FAMILY 1 +#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1 + #define __IAR_M0_FAMILY 1 +#else + #define __IAR_M0_FAMILY 0 +#endif + + +#ifndef __ASM + #define __ASM __asm +#endif + +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +#ifndef __INLINE + #define __INLINE inline +#endif + +#ifndef __NO_RETURN + #if __ICCARM_V8 + #define __NO_RETURN __attribute__((__noreturn__)) + #else + #define __NO_RETURN _Pragma("object_attribute=__noreturn") + #endif +#endif + +#ifndef __PACKED + #if __ICCARM_V8 + #define __PACKED __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED __packed + #endif +#endif + +#ifndef __PACKED_STRUCT + #if __ICCARM_V8 + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_STRUCT __packed struct + #endif +#endif + +#ifndef __PACKED_UNION + #if __ICCARM_V8 + #define __PACKED_UNION union __attribute__((packed, aligned(1))) + #else + /* Needs IAR language extensions */ + #define __PACKED_UNION __packed union + #endif +#endif + +#ifndef __RESTRICT + #if __ICCARM_V8 + #define __RESTRICT __restrict + #else + /* Needs IAR language extensions */ + #define __RESTRICT restrict + #endif +#endif + +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif + +#ifndef __FORCEINLINE + #define __FORCEINLINE _Pragma("inline=forced") +#endif + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE +#endif + +#ifndef __UNALIGNED_UINT16_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint16_t __iar_uint16_read(void const *ptr) +{ + return *(__packed uint16_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR) +#endif + + +#ifndef __UNALIGNED_UINT16_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val) +{ + *(__packed uint16_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32_READ +#pragma language=save +#pragma language=extended +__IAR_FT uint32_t __iar_uint32_read(void const *ptr) +{ + return *(__packed uint32_t*)(ptr); +} +#pragma language=restore +#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR) +#endif + +#ifndef __UNALIGNED_UINT32_WRITE +#pragma language=save +#pragma language=extended +__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val) +{ + *(__packed uint32_t*)(ptr) = val;; +} +#pragma language=restore +#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL) +#endif + +#ifndef __UNALIGNED_UINT32 /* deprecated */ +#pragma language=save +#pragma language=extended +__packed struct __iar_u32 { uint32_t v; }; +#pragma language=restore +#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v) +#endif + +#ifndef __USED + #if __ICCARM_V8 + #define __USED __attribute__((used)) + #else + #define __USED _Pragma("__root") + #endif +#endif + +#ifndef __WEAK + #if __ICCARM_V8 + #define __WEAK __attribute__((weak)) + #else + #define __WEAK _Pragma("__weak") + #endif +#endif + +#ifndef __PROGRAM_START +#define __PROGRAM_START __iar_program_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP CSTACK$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT CSTACK$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __vector_table +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE @".intvec" +#endif + +#ifndef __ICCARM_INTRINSICS_VERSION__ + #define __ICCARM_INTRINSICS_VERSION__ 0 +#endif + +#if __ICCARM_INTRINSICS_VERSION__ == 2 + + #if defined(__CLZ) + #undef __CLZ + #endif + #if defined(__REVSH) + #undef __REVSH + #endif + #if defined(__RBIT) + #undef __RBIT + #endif + #if defined(__SSAT) + #undef __SSAT + #endif + #if defined(__USAT) + #undef __USAT + #endif + + #include "iccarm_builtin.h" + + #define __disable_fault_irq __iar_builtin_disable_fiq + #define __disable_irq __iar_builtin_disable_interrupt + #define __enable_fault_irq __iar_builtin_enable_fiq + #define __enable_irq __iar_builtin_enable_interrupt + #define __arm_rsr __iar_builtin_rsr + #define __arm_wsr __iar_builtin_wsr + + + #define __get_APSR() (__arm_rsr("APSR")) + #define __get_BASEPRI() (__arm_rsr("BASEPRI")) + #define __get_CONTROL() (__arm_rsr("CONTROL")) + #define __get_FAULTMASK() (__arm_rsr("FAULTMASK")) + + #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + #define __get_FPSCR() (__arm_rsr("FPSCR")) + #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE))) + #else + #define __get_FPSCR() ( 0 ) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #define __get_IPSR() (__arm_rsr("IPSR")) + #define __get_MSP() (__arm_rsr("MSP")) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __get_MSPLIM() (0U) + #else + #define __get_MSPLIM() (__arm_rsr("MSPLIM")) + #endif + #define __get_PRIMASK() (__arm_rsr("PRIMASK")) + #define __get_PSP() (__arm_rsr("PSP")) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __get_PSPLIM() (0U) + #else + #define __get_PSPLIM() (__arm_rsr("PSPLIM")) + #endif + + #define __get_xPSR() (__arm_rsr("xPSR")) + + #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE))) + #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE))) + #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE))) + #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE))) + #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + #define __set_MSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE))) + #endif + #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE))) + #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE))) + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __set_PSPLIM(VALUE) ((void)(VALUE)) + #else + #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE))) + #endif + + #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS")) + #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE))) + #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS")) + #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE))) + #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS")) + #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE))) + #define __TZ_get_SP_NS() (__arm_rsr("SP_NS")) + #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE))) + #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS")) + #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE))) + #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS")) + #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE))) + #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS")) + #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE))) + + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + #define __TZ_get_PSPLIM_NS() (0U) + #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE)) + #else + #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS")) + #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE))) + #endif + + #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS")) + #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE))) + + #define __NOP __iar_builtin_no_operation + + #define __CLZ __iar_builtin_CLZ + #define __CLREX __iar_builtin_CLREX + + #define __DMB __iar_builtin_DMB + #define __DSB __iar_builtin_DSB + #define __ISB __iar_builtin_ISB + + #define __LDREXB __iar_builtin_LDREXB + #define __LDREXH __iar_builtin_LDREXH + #define __LDREXW __iar_builtin_LDREX + + #define __RBIT __iar_builtin_RBIT + #define __REV __iar_builtin_REV + #define __REV16 __iar_builtin_REV16 + + __IAR_FT int16_t __REVSH(int16_t val) + { + return (int16_t) __iar_builtin_REVSH(val); + } + + #define __ROR __iar_builtin_ROR + #define __RRX __iar_builtin_RRX + + #define __SEV __iar_builtin_SEV + + #if !__IAR_M0_FAMILY + #define __SSAT __iar_builtin_SSAT + #endif + + #define __STREXB __iar_builtin_STREXB + #define __STREXH __iar_builtin_STREXH + #define __STREXW __iar_builtin_STREX + + #if !__IAR_M0_FAMILY + #define __USAT __iar_builtin_USAT + #endif + + #define __WFE __iar_builtin_WFE + #define __WFI __iar_builtin_WFI + + #if __ARM_MEDIA__ + #define __SADD8 __iar_builtin_SADD8 + #define __QADD8 __iar_builtin_QADD8 + #define __SHADD8 __iar_builtin_SHADD8 + #define __UADD8 __iar_builtin_UADD8 + #define __UQADD8 __iar_builtin_UQADD8 + #define __UHADD8 __iar_builtin_UHADD8 + #define __SSUB8 __iar_builtin_SSUB8 + #define __QSUB8 __iar_builtin_QSUB8 + #define __SHSUB8 __iar_builtin_SHSUB8 + #define __USUB8 __iar_builtin_USUB8 + #define __UQSUB8 __iar_builtin_UQSUB8 + #define __UHSUB8 __iar_builtin_UHSUB8 + #define __SADD16 __iar_builtin_SADD16 + #define __QADD16 __iar_builtin_QADD16 + #define __SHADD16 __iar_builtin_SHADD16 + #define __UADD16 __iar_builtin_UADD16 + #define __UQADD16 __iar_builtin_UQADD16 + #define __UHADD16 __iar_builtin_UHADD16 + #define __SSUB16 __iar_builtin_SSUB16 + #define __QSUB16 __iar_builtin_QSUB16 + #define __SHSUB16 __iar_builtin_SHSUB16 + #define __USUB16 __iar_builtin_USUB16 + #define __UQSUB16 __iar_builtin_UQSUB16 + #define __UHSUB16 __iar_builtin_UHSUB16 + #define __SASX __iar_builtin_SASX + #define __QASX __iar_builtin_QASX + #define __SHASX __iar_builtin_SHASX + #define __UASX __iar_builtin_UASX + #define __UQASX __iar_builtin_UQASX + #define __UHASX __iar_builtin_UHASX + #define __SSAX __iar_builtin_SSAX + #define __QSAX __iar_builtin_QSAX + #define __SHSAX __iar_builtin_SHSAX + #define __USAX __iar_builtin_USAX + #define __UQSAX __iar_builtin_UQSAX + #define __UHSAX __iar_builtin_UHSAX + #define __USAD8 __iar_builtin_USAD8 + #define __USADA8 __iar_builtin_USADA8 + #define __SSAT16 __iar_builtin_SSAT16 + #define __USAT16 __iar_builtin_USAT16 + #define __UXTB16 __iar_builtin_UXTB16 + #define __UXTAB16 __iar_builtin_UXTAB16 + #define __SXTB16 __iar_builtin_SXTB16 + #define __SXTAB16 __iar_builtin_SXTAB16 + #define __SMUAD __iar_builtin_SMUAD + #define __SMUADX __iar_builtin_SMUADX + #define __SMMLA __iar_builtin_SMMLA + #define __SMLAD __iar_builtin_SMLAD + #define __SMLADX __iar_builtin_SMLADX + #define __SMLALD __iar_builtin_SMLALD + #define __SMLALDX __iar_builtin_SMLALDX + #define __SMUSD __iar_builtin_SMUSD + #define __SMUSDX __iar_builtin_SMUSDX + #define __SMLSD __iar_builtin_SMLSD + #define __SMLSDX __iar_builtin_SMLSDX + #define __SMLSLD __iar_builtin_SMLSLD + #define __SMLSLDX __iar_builtin_SMLSLDX + #define __SEL __iar_builtin_SEL + #define __QADD __iar_builtin_QADD + #define __QSUB __iar_builtin_QSUB + #define __PKHBT __iar_builtin_PKHBT + #define __PKHTB __iar_builtin_PKHTB + #endif + +#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #define __CLZ __cmsis_iar_clz_not_active + #define __SSAT __cmsis_iar_ssat_not_active + #define __USAT __cmsis_iar_usat_not_active + #define __RBIT __cmsis_iar_rbit_not_active + #define __get_APSR __cmsis_iar_get_APSR_not_active + #endif + + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #define __get_FPSCR __cmsis_iar_get_FPSR_not_active + #define __set_FPSCR __cmsis_iar_set_FPSR_not_active + #endif + + #ifdef __INTRINSICS_INCLUDED + #error intrinsics.h is already included previously! + #endif + + #include + + #if __IAR_M0_FAMILY + /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */ + #undef __CLZ + #undef __SSAT + #undef __USAT + #undef __RBIT + #undef __get_APSR + + __STATIC_INLINE uint8_t __CLZ(uint32_t data) + { + if (data == 0U) { return 32U; } + + uint32_t count = 0U; + uint32_t mask = 0x80000000U; + + while ((data & mask) == 0U) + { + count += 1U; + mask = mask >> 1U; + } + return count; + } + + __STATIC_INLINE uint32_t __RBIT(uint32_t v) + { + uint8_t sc = 31U; + uint32_t r = v; + for (v >>= 1U; v; v >>= 1U) + { + r <<= 1U; + r |= v & 1U; + sc--; + } + return (r << sc); + } + + __STATIC_INLINE uint32_t __get_APSR(void) + { + uint32_t res; + __asm("MRS %0,APSR" : "=r" (res)); + return res; + } + + #endif + + #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) )) + #undef __get_FPSCR + #undef __set_FPSCR + #define __get_FPSCR() (0) + #define __set_FPSCR(VALUE) ((void)VALUE) + #endif + + #pragma diag_suppress=Pe940 + #pragma diag_suppress=Pe177 + + #define __enable_irq __enable_interrupt + #define __disable_irq __disable_interrupt + #define __NOP __no_operation + + #define __get_xPSR __get_PSR + + #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0) + + __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr) + { + return __LDREX((unsigned long *)ptr); + } + + __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr) + { + return __STREX(value, (unsigned long *)ptr); + } + #endif + + + /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + #if (__CORTEX_M >= 0x03) + + __IAR_FT uint32_t __RRX(uint32_t value) + { + uint32_t result; + __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc"); + return(result); + } + + __IAR_FT void __set_BASEPRI_MAX(uint32_t value) + { + __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value)); + } + + + #define __enable_fault_irq __enable_fiq + #define __disable_fault_irq __disable_fiq + + + #endif /* (__CORTEX_M >= 0x03) */ + + __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2) + { + return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2)); + } + + #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + __IAR_FT uint32_t __get_MSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,MSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_MSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR MSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __get_PSPLIM(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __set_PSPLIM(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_CONTROL_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,CONTROL_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value) + { + __asm volatile("MSR CONTROL_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PSP_NS(uint32_t value) + { + __asm volatile("MSR PSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_MSP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSP_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSP_NS(uint32_t value) + { + __asm volatile("MSR MSP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_SP_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,SP_NS" : "=r" (res)); + return res; + } + __IAR_FT void __TZ_set_SP_NS(uint32_t value) + { + __asm volatile("MSR SP_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value) + { + __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value) + { + __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value) + { + __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value)); + } + + __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void) + { + uint32_t res; + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + res = 0U; + #else + __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res)); + #endif + return res; + } + + __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value) + { + #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)value; + #else + __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value)); + #endif + } + + __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void) + { + uint32_t res; + __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res)); + return res; + } + + __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value) + { + __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value)); + } + + #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */ + +#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value)) + +#if __IAR_M0_FAMILY + __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) + { + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; + } + + __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) + { + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; + } +#endif + +#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */ + + __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr) + { + uint32_t res; + __ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr) + { + uint32_t res; + __ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDRT(volatile uint32_t *addr) + { + uint32_t res; + __ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory"); + return res; + } + + __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr) + { + __ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr) + { + __ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory"); + } + + __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr) + { + __ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory"); + } + +#endif /* (__CORTEX_M >= 0x03) */ + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + + + __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDA(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr) + { + __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr) + { + __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr) + { + __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory"); + } + + __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint8_t)res); + } + + __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return ((uint16_t)res); + } + + __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + + __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) + { + uint32_t res; + __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory"); + return res; + } + +#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */ + +#undef __IAR_FT +#undef __IAR_M0_FAMILY +#undef __ICCARM_V8 + +#pragma diag_default=Pe940 +#pragma diag_default=Pe177 + +#endif /* __CMSIS_ICCARM_H__ */ diff --git a/Drivers/CMSIS/Include/cmsis_version.h b/Drivers/CMSIS/Include/cmsis_version.h new file mode 100644 index 0000000..f2e2746 --- /dev/null +++ b/Drivers/CMSIS/Include/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.3 + * @date 24. June 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 3U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/Drivers/CMSIS/Include/core_armv81mml.h b/Drivers/CMSIS/Include/core_armv81mml.h new file mode 100644 index 0000000..8441e57 --- /dev/null +++ b/Drivers/CMSIS/Include/core_armv81mml.h @@ -0,0 +1,2968 @@ +/**************************************************************************//** + * @file core_armv81mml.h + * @brief CMSIS Armv8.1-M Mainline Core Peripheral Access Layer Header File + * @version V1.0.0 + * @date 15. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2018-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV81MML_H_GENERIC +#define __CORE_ARMV81MML_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMV81MML + @{ + */ + +#include "cmsis_version.h" + +#define __ARM_ARCH_8M_MAIN__ 1 // patching for now +/* CMSIS ARMV81MML definitions */ +#define __ARMv81MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv81MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv81MML_CMSIS_VERSION ((__ARMv81MML_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv81MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (81U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV81MML_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV81MML_H_DEPENDANT +#define __CORE_ARMV81MML_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv81MML_REV + #define __ARMv81MML_REV 0x0000U + #warning "__ARMv81MML_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv81MML */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[29U]; + __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */ + __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */ + __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */ + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Integration Write Register Definitions */ +#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */ +#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */ + +/* ITM Integration Read Register Definitions */ +#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */ +#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */ + +/* ITM Integration Mode Control Register Definitions */ +#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */ +#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */ +#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */ +#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_PXN_Pos 4U /*!< MPU RLAR: PXN Position */ +#define MPU_RLAR_PXN_Msk (0x1UL << MPU_RLAR_PXN_Pos) /*!< MPU RLAR: PXN Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV81MML_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_armv8mbl.h b/Drivers/CMSIS/Include/core_armv8mbl.h new file mode 100644 index 0000000..344dca5 --- /dev/null +++ b/Drivers/CMSIS/Include/core_armv8mbl.h @@ -0,0 +1,1921 @@ +/**************************************************************************//** + * @file core_armv8mbl.h + * @brief CMSIS Armv8-M Baseline Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV8MBL_H_GENERIC +#define __CORE_ARMV8MBL_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMv8MBL + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS definitions */ +#define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M ( 2U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MBL_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV8MBL_H_DEPENDANT +#define __CORE_ARMV8MBL_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv8MBL_REV + #define __ARMv8MBL_REV 0x0000U + #warning "__ARMv8MBL_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif + + #ifndef __ETM_PRESENT + #define __ETM_PRESENT 0U + #warning "__ETM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MTB_PRESENT + #define __MTB_PRESENT 0U + #warning "__MTB_PRESENT not defined in device header file; using default!" + #endif + +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv8MBL */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + uint32_t RESERVED0[6U]; + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[809U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ + uint32_t RESERVED4[4U]; + __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ +#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI Periodic Synchronization Control Register Definitions */ +#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ +#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ + +/* TPI Software Lock Status Register Definitions */ +#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ +#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ + +#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ +#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ + +#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ +#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + uint32_t RESERVED0[7U]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 1U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#endif +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ +#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MBL_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_armv8mml.h b/Drivers/CMSIS/Include/core_armv8mml.h new file mode 100644 index 0000000..5ddb8ae --- /dev/null +++ b/Drivers/CMSIS/Include/core_armv8mml.h @@ -0,0 +1,2835 @@ +/**************************************************************************//** + * @file core_armv8mml.h + * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 12. September 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_ARMV8MML_H_GENERIC +#define __CORE_ARMV8MML_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_ARMv8MML + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS Armv8MML definitions */ +#define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \ + __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (81U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined(__ARM_FEATURE_DSP) + #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MML_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_ARMV8MML_H_DEPENDANT +#define __CORE_ARMV8MML_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __ARMv8MML_REV + #define __ARMv8MML_REV 0x0000U + #warning "__ARMv8MML_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group ARMv8MML */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[809U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */ + uint32_t RESERVED4[4U]; + __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */ +#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI Periodic Synchronization Control Register Definitions */ +#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */ +#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */ + +/* TPI Software Lock Status Register Definitions */ +#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */ +#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */ + +#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */ +#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */ + +#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */ +#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_ARMV8MML_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm0.h b/Drivers/CMSIS/Include/core_cm0.h new file mode 100644 index 0000000..cafae5a --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm0.h @@ -0,0 +1,952 @@ +/**************************************************************************//** + * @file core_cm0.h + * @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File + * @version V5.0.6 + * @date 13. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0_H_GENERIC +#define __CORE_CM0_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M0 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM0 definitions */ +#define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \ + __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (0U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0_H_DEPENDANT +#define __CORE_CM0_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0_REV + #define __CM0_REV 0x0000U + #warning "__CM0_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M0 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + Address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = 0x0U; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + /* ARM Application Note 321 states that the M0 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = 0x0U; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm0plus.h b/Drivers/CMSIS/Include/core_cm0plus.h new file mode 100644 index 0000000..d104965 --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm0plus.h @@ -0,0 +1,1085 @@ +/**************************************************************************//** + * @file core_cm0plus.h + * @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File + * @version V5.0.7 + * @date 13. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM0PLUS_H_GENERIC +#define __CORE_CM0PLUS_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex-M0+ + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM0+ definitions */ +#define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \ + __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (0U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM0PLUS_H_DEPENDANT +#define __CORE_CM0PLUS_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM0PLUS_REV + #define __CM0PLUS_REV 0x0000U + #warning "__CM0PLUS_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex-M0+ */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 1U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M0+ Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M0+ header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0+ */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t vectors = SCB->VTOR; +#else + uint32_t vectors = 0x0U; +#endif + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + /* ARM Application Note 321 states that the M0+ does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t vectors = SCB->VTOR; +#else + uint32_t vectors = 0x0U; +#endif + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM0PLUS_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm1.h b/Drivers/CMSIS/Include/core_cm1.h new file mode 100644 index 0000000..76b4569 --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm1.h @@ -0,0 +1,979 @@ +/**************************************************************************//** + * @file core_cm1.h + * @brief CMSIS Cortex-M1 Core Peripheral Access Layer Header File + * @version V1.0.1 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM1_H_GENERIC +#define __CORE_CM1_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M1 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM1 definitions */ +#define __CM1_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM1_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM1_CMSIS_VERSION ((__CM1_CMSIS_VERSION_MAIN << 16U) | \ + __CM1_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (1U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM1_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM1_H_DEPENDANT +#define __CORE_CM1_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM1_REV + #define __CM1_REV 0x0100U + #warning "__CM1_REV not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M1 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + uint32_t RESERVED0; + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_ITCMUAEN_Pos 4U /*!< ACTLR: Instruction TCM Upper Alias Enable Position */ +#define SCnSCB_ACTLR_ITCMUAEN_Msk (1UL << SCnSCB_ACTLR_ITCMUAEN_Pos) /*!< ACTLR: Instruction TCM Upper Alias Enable Mask */ + +#define SCnSCB_ACTLR_ITCMLAEN_Pos 3U /*!< ACTLR: Instruction TCM Lower Alias Enable Position */ +#define SCnSCB_ACTLR_ITCMLAEN_Msk (1UL << SCnSCB_ACTLR_ITCMLAEN_Pos) /*!< ACTLR: Instruction TCM Lower Alias Enable Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Cortex-M1 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the Cortex-M1 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M1 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + Address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)0x0U; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + /* ARM Application Note 321 states that the M1 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)0x0U; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM1_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm23.h b/Drivers/CMSIS/Include/core_cm23.h new file mode 100644 index 0000000..b79c6af --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm23.h @@ -0,0 +1,1996 @@ +/**************************************************************************//** + * @file core_cm23.h + * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM23_H_GENERIC +#define __CORE_CM23_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M23 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS definitions */ +#define __CM23_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM23_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \ + __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (23U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM23_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM23_H_DEPENDANT +#define __CORE_CM23_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM23_REV + #define __CM23_REV 0x0000U + #warning "__CM23_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 0U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif + + #ifndef __ETM_PRESENT + #define __ETM_PRESENT 0U + #warning "__ETM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MTB_PRESENT + #define __MTB_PRESENT 0U + #warning "__MTB_PRESENT not defined in device header file; using default!" + #endif + +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M23 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ +#else + uint32_t RESERVED0; +#endif + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED1; + __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + uint32_t RESERVED0[6U]; + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ + __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ + __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration Test FIFO Test Data 0 Register Definitions */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ +#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ +#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ +#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ + +/* TPI Integration Test ATB Control Register 2 Register Definitions */ +#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ +#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ + +#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ +#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ + +#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ +#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ + +#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ +#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ + +/* TPI Integration Test FIFO Test Data 1 Register Definitions */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ +#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ +#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ +#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ + +/* TPI Integration Test ATB Control Register 0 Definitions */ +#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ +#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ + +#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ +#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ + +#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ +#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ + +#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ +#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + uint32_t RESERVED0[7U]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 1U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#endif +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register */ +#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */ +#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else +/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M23 */ +/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M23 */ + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + +#define __NVIC_SetPriorityGrouping(X) (void)(X) +#define __NVIC_GetPriorityGrouping() (0U) + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + If VTOR is not present address 0 must be mapped to SRAM. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + uint32_t *vectors = (uint32_t *)SCB->VTOR; +#else + uint32_t *vectors = (uint32_t *)0x0U; +#endif + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM23_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm3.h b/Drivers/CMSIS/Include/core_cm3.h new file mode 100644 index 0000000..8157ca7 --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm3.h @@ -0,0 +1,1937 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 13. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M3 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (3U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200U + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1U]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ +#endif + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + /* ARM Application Note 321 states that the M3 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm33.h b/Drivers/CMSIS/Include/core_cm33.h new file mode 100644 index 0000000..7fed59a --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm33.h @@ -0,0 +1,2910 @@ +/**************************************************************************//** + * @file core_cm33.h + * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM33_H_GENERIC +#define __CORE_CM33_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M33 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM33 definitions */ +#define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \ + __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (33U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined (__TARGET_FPU_VFP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined (__ARM_FP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined (__ARMVFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined (__TI_VFP_SUPPORT__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined (__FPU_VFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM33_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM33_H_DEPENDANT +#define __CORE_CM33_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM33_REV + #define __CM33_REV 0x0000U + #warning "__CM33_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M33 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ + __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ + __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration Test FIFO Test Data 0 Register Definitions */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ +#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ +#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ +#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ + +/* TPI Integration Test ATB Control Register 2 Register Definitions */ +#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ +#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ + +#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ +#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ + +#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ +#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ + +#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ +#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ + +/* TPI Integration Test FIFO Test Data 1 Register Definitions */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ +#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ +#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ +#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ + +/* TPI Integration Test ATB Control Register 0 Definitions */ +#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ +#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ + +#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ +#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ + +#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ +#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ + +#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ +#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM33_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm35p.h b/Drivers/CMSIS/Include/core_cm35p.h new file mode 100644 index 0000000..5579c82 --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm35p.h @@ -0,0 +1,2910 @@ +/**************************************************************************//** + * @file core_cm35p.h + * @brief CMSIS Cortex-M35P Core Peripheral Access Layer Header File + * @version V1.0.0 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM35P_H_GENERIC +#define __CORE_CM35P_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M35P + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM35P definitions */ +#define __CM35P_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM35P_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM35P_CMSIS_VERSION ((__CM35P_CMSIS_VERSION_MAIN << 16U) | \ + __CM35P_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (35U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined (__TARGET_FPU_VFP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined (__ARM_FP) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined (__ARMVFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + + #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U) + #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U) + #define __DSP_USED 1U + #else + #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)" + #define __DSP_USED 0U + #endif + #else + #define __DSP_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined (__TI_VFP_SUPPORT__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined (__FPU_VFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM35P_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM35P_H_DEPENDANT +#define __CORE_CM35P_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM35P_REV + #define __CM35P_REV 0x0000U + #warning "__CM35P_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __SAUREGION_PRESENT + #define __SAUREGION_PRESENT 0U + #warning "__SAUREGION_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DSP_PRESENT + #define __DSP_PRESENT 0U + #warning "__DSP_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M35P */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core SAU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */ +#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */ + uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */ + uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */ + uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */ +#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */ + +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[16U]; + __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[16U]; + __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[16U]; + __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[16U]; + __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[16U]; + __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */ + uint32_t RESERVED5[16U]; + __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED6[580U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */ + uint32_t RESERVED3[92U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */ +#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */ + +#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */ +#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */ + +#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */ +#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */ +#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */ +#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */ + +#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */ +#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */ +#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */ +#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */ + +#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */ +#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */ +#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */ +#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */ + +#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */ +#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */ + +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */ +#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */ + +#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */ +#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */ +#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */ +#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Non-Secure Access Control Register Definitions */ +#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */ +#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */ + +#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */ +#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */ + +#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */ +#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ + __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */ + uint32_t RESERVED6[4U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Stimulus Port Register Definitions */ +#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */ +#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */ + +#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */ +#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */ + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */ +#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */ + +#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */ +#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + uint32_t RESERVED3[1U]; + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED4[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + uint32_t RESERVED5[1U]; + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED6[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + uint32_t RESERVED7[1U]; + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED8[1U]; + __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */ + uint32_t RESERVED9[1U]; + __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */ + uint32_t RESERVED10[1U]; + __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */ + uint32_t RESERVED11[1U]; + __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */ + uint32_t RESERVED12[1U]; + __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */ + uint32_t RESERVED13[1U]; + __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */ + uint32_t RESERVED14[1U]; + __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */ + uint32_t RESERVED15[1U]; + __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */ + uint32_t RESERVED16[1U]; + __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */ + uint32_t RESERVED17[1U]; + __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */ + uint32_t RESERVED18[1U]; + __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */ + uint32_t RESERVED19[1U]; + __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */ + uint32_t RESERVED20[1U]; + __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */ + uint32_t RESERVED21[1U]; + __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */ + uint32_t RESERVED22[1U]; + __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */ + uint32_t RESERVED23[1U]; + __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */ + uint32_t RESERVED24[1U]; + __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */ + uint32_t RESERVED25[1U]; + __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */ + uint32_t RESERVED26[1U]; + __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */ + uint32_t RESERVED27[1U]; + __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */ + uint32_t RESERVED28[1U]; + __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */ + uint32_t RESERVED29[1U]; + __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */ + uint32_t RESERVED30[1U]; + __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */ + uint32_t RESERVED31[1U]; + __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */ + uint32_t RESERVED32[934U]; + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ + uint32_t RESERVED33[1U]; + __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */ +#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */ +#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */ + +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */ +#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */ + +#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */ +#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */ + __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */ + __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */ +#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration Test FIFO Test Data 0 Register Definitions */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */ +#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */ +#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */ +#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */ + +#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */ +#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */ + +/* TPI Integration Test ATB Control Register 2 Register Definitions */ +#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */ +#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */ + +#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */ +#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */ + +#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */ +#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */ + +#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */ +#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */ + +/* TPI Integration Test FIFO Test Data 1 Register Definitions */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */ +#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */ + +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */ +#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */ + +#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */ +#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */ +#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */ +#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */ + +#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */ +#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */ + +/* TPI Integration Test ATB Control Register 0 Definitions */ +#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */ +#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */ + +#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */ +#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */ + +#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */ +#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */ + +#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */ +#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */ +#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */ + __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */ + __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */ + __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */ + uint32_t RESERVED0[1]; + union { + __IOM uint32_t MAIR[2]; + struct { + __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */ + __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */ + }; + }; +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */ +#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */ + +#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */ +#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */ + +#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */ +#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */ + +#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */ +#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */ + +/* MPU Region Limit Address Register Definitions */ +#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */ +#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */ + +#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */ +#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */ + +#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */ +#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */ + +/* MPU Memory Attribute Indirection Register 0 Definitions */ +#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */ +#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */ + +#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */ +#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */ + +#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */ +#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */ + +#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */ +#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */ + +/* MPU Memory Attribute Indirection Register 1 Definitions */ +#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */ +#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */ + +#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */ +#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */ + +#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */ +#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */ + +#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */ +#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SAU Security Attribution Unit (SAU) + \brief Type definitions for the Security Attribution Unit (SAU) + @{ + */ + +/** + \brief Structure type to access the Security Attribution Unit (SAU). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */ + __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */ +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */ + __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */ +#else + uint32_t RESERVED0[3]; +#endif + __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */ + __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */ +} SAU_Type; + +/* SAU Control Register Definitions */ +#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */ +#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */ + +#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */ +#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */ + +/* SAU Type Register Definitions */ +#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */ +#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) +/* SAU Region Number Register Definitions */ +#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */ +#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */ + +/* SAU Region Base Address Register Definitions */ +#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */ +#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */ + +/* SAU Region Limit Address Register Definitions */ +#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */ +#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */ + +#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */ +#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */ + +#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */ +#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + +/* Secure Fault Status Register Definitions */ +#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */ +#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */ + +#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */ +#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */ + +#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */ +#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */ + +#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */ +#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */ + +#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */ +#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */ + +#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */ +#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */ + +#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */ +#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */ + +#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */ +#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */ + +/*@} end of group CMSIS_SAU */ +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */ +#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */ + +#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */ +#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */ + +#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */ +#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */ + +#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */ +#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */ + +#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */ +#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */ + +#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */ +#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */ +#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */ +#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ + uint32_t RESERVED4[1U]; + __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */ + __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */ +#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/* Debug Authentication Control Register Definitions */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */ +#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */ + +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */ + +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */ +#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */ + +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */ +#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */ + +/* Debug Security Control and Status Register Definitions */ +#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */ +#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */ + +#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */ +#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */ + +#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */ +#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ + #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ + #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ + #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ + #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ + #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ + #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ + #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ + #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + + #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ + #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ + #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ + #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ + #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ + #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ + #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ + #endif + + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */ + #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */ + #endif + + #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ + #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */ + #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */ + #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */ + #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */ + #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */ + + #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */ + #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */ + #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */ + #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */ + #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */ + + #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */ + #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */ + #endif + + #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */ + #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */ + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* Special LR values for Secure/Non-Secure call handling and exception handling */ + +/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */ +#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */ + +/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */ +#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */ +#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */ +#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */ +#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */ +#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */ +#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */ +#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */ + +/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */ +#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */ +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */ +#else +#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */ +#endif + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Get Interrupt Target State + \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + \return 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Target State + \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Clear Interrupt Target State + \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 if interrupt is assigned to Secure + 1 if interrupt is assigned to Non Secure + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL))); + return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief Set Priority Grouping (non-secure) + \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB_NS->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB_NS->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping (non-secure) + \details Reads the priority grouping field from the non-secure NVIC when in secure state. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void) +{ + return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt (non-secure) + \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Interrupt Enable status (non-secure) + \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt (non-secure) + \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Pending Interrupt (non-secure) + \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt (non-secure) + \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt (non-secure) + \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt (non-secure) + \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority (non-secure) + \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every non-secure processor exception. + */ +__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority (non-secure) + \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} +#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_NVICFunctions */ + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv8.h" + +#endif + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## SAU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SAUFunctions SAU Functions + \brief Functions that configure the SAU. + @{ + */ + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + +/** + \brief Enable SAU + \details Enables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Enable(void) +{ + SAU->CTRL |= (SAU_CTRL_ENABLE_Msk); +} + + + +/** + \brief Disable SAU + \details Disables the Security Attribution Unit (SAU). + */ +__STATIC_INLINE void TZ_SAU_Disable(void) +{ + SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk); +} + +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +/*@} end of CMSIS_Core_SAUFunctions */ + + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +/** + \brief System Tick Configuration (non-secure) + \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function TZ_SysTick_Config_NS is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + + */ +__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} +#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */ + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM35P_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm4.h b/Drivers/CMSIS/Include/core_cm4.h new file mode 100644 index 0000000..12c023b --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm4.h @@ -0,0 +1,2124 @@ +/**************************************************************************//** + * @file core_cm4.h + * @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File + * @version V5.1.0 + * @date 13. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM4_H_GENERIC +#define __CORE_CM4_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M4 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM4 definitions */ +#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \ + __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (4U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM4_H_DEPENDANT +#define __CORE_CM4_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM4_REV + #define __CM4_REV 0x0000U + #warning "__CM4_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M4 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + /* ARM Application Note 321 states that the M4 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = FPU->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM4_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_cm7.h b/Drivers/CMSIS/Include/core_cm7.h new file mode 100644 index 0000000..c4515d8 --- /dev/null +++ b/Drivers/CMSIS/Include/core_cm7.h @@ -0,0 +1,2725 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V5.1.1 + * @date 28. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (7U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */ +#define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */ + +#define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */ +#define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */ + +#define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */ +#define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */ + +#define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */ +#define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */ + +#define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */ +#define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */ + +#define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */ +#define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */ + +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + +#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ +#define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */ + + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief I-Cache Invalidate by address + \details Invalidates I-Cache for the given address. + I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + I-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] isize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (void *addr, int32_t isize) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if ( isize > 0 ) { + int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_ICACHE_LINE_SIZE; + op_size -= __SCB_ICACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */ + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address. + D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned and invalidated. + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_sc000.h b/Drivers/CMSIS/Include/core_sc000.h new file mode 100644 index 0000000..cf92577 --- /dev/null +++ b/Drivers/CMSIS/Include/core_sc000.h @@ -0,0 +1,1025 @@ +/**************************************************************************//** + * @file core_sc000.h + * @brief CMSIS SC000 Core Peripheral Access Layer Header File + * @version V5.0.6 + * @date 12. November 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC000_H_GENERIC +#define __CORE_SC000_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC000 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS SC000 definitions */ +#define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \ + __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_SC (000U) /*!< Cortex secure core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC000_H_DEPENDANT +#define __CORE_SC000_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC000_REV + #define __SC000_REV 0x0000U + #warning "__SC000_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 2U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC000 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */ + uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t _reserved0:1; /*!< bit: 0 Reserved */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[31U]; + __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RSERVED1[31U]; + __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[31U]; + __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[31U]; + uint32_t RESERVED4[64U]; + __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */ +} NVIC_Type; + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + uint32_t RESERVED0[1U]; + __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + uint32_t RESERVED1[154U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 8U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0xFFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief SC000 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor. + Therefore they are not covered by the SC000 header file. + @{ + */ +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else +/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for SC000 */ +/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for SC000 */ + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +/*#define NVIC_GetActive __NVIC_GetActive not available for SC000 */ + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/* Interrupt Priorities are WORD accessible only under Armv6-M */ +/* The following MACROS handle generation of the register offset and byte masks */ +#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL) +#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) ) +#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) ) + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } + else + { + SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) | + (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn))); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + /* ARM Application Note 321 states that the M0 and M0+ do not require the architectural barrier - assume SC000 is the same */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + SCB_AIRCR_SYSRESETREQ_Msk); + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC000_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/core_sc300.h b/Drivers/CMSIS/Include/core_sc300.h new file mode 100644 index 0000000..40f3af8 --- /dev/null +++ b/Drivers/CMSIS/Include/core_sc300.h @@ -0,0 +1,1912 @@ +/**************************************************************************//** + * @file core_sc300.h + * @brief CMSIS SC300 Core Peripheral Access Layer Header File + * @version V5.0.8 + * @date 31. May 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_SC300_H_GENERIC +#define __CORE_SC300_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup SC3000 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS SC300 definitions */ +#define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \ + __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_SC (300U) /*!< Cortex secure core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_SC300_H_DEPENDANT +#define __CORE_SC300_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __SC300_REV + #define __SC300_REV 0x0000U + #warning "__SC300_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group SC300 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED1[129U]; + __IOM uint32_t SFCR; /*!< Offset: 0x290 (R/W) Security Features Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + /* ARM Application Note 321 states that the M3 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_SC300_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/Drivers/CMSIS/Include/mpu_armv7.h b/Drivers/CMSIS/Include/mpu_armv7.h new file mode 100644 index 0000000..66ef59b --- /dev/null +++ b/Drivers/CMSIS/Include/mpu_armv7.h @@ -0,0 +1,272 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.1.0 + * @date 08. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2017-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if shareable) or 010b (if non-shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/Drivers/CMSIS/Include/mpu_armv8.h b/Drivers/CMSIS/Include/mpu_armv8.h new file mode 100644 index 0000000..0041d4d --- /dev/null +++ b/Drivers/CMSIS/Include/mpu_armv8.h @@ -0,0 +1,346 @@ +/****************************************************************************** + * @file mpu_armv8.h + * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU + * @version V5.1.0 + * @date 08. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2017-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV8_H +#define ARM_MPU_ARMV8_H + +/** \brief Attribute for device memory (outer only) */ +#define ARM_MPU_ATTR_DEVICE ( 0U ) + +/** \brief Attribute for non-cacheable, normal memory */ +#define ARM_MPU_ATTR_NON_CACHEABLE ( 4U ) + +/** \brief Attribute for normal memory (outer and inner) +* \param NT Non-Transient: Set to 1 for non-transient data. +* \param WB Write-Back: Set to 1 to use write-back update policy. +* \param RA Read Allocation: Set to 1 to use cache allocation on read miss. +* \param WA Write Allocation: Set to 1 to use cache allocation on write miss. +*/ +#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \ + (((NT & 1U) << 3U) | ((WB & 1U) << 2U) | ((RA & 1U) << 1U) | (WA & 1U)) + +/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGnRnE (0U) + +/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGnRE (1U) + +/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_nGRE (2U) + +/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */ +#define ARM_MPU_ATTR_DEVICE_GRE (3U) + +/** \brief Memory Attribute +* \param O Outer memory attributes +* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes +*/ +#define ARM_MPU_ATTR(O, I) (((O & 0xFU) << 4U) | (((O & 0xFU) != 0U) ? (I & 0xFU) : ((I & 0x3U) << 2U))) + +/** \brief Normal memory non-shareable */ +#define ARM_MPU_SH_NON (0U) + +/** \brief Normal memory outer shareable */ +#define ARM_MPU_SH_OUTER (2U) + +/** \brief Normal memory inner shareable */ +#define ARM_MPU_SH_INNER (3U) + +/** \brief Memory access permissions +* \param RO Read-Only: Set to 1 for read-only memory. +* \param NP Non-Privileged: Set to 1 for non-privileged memory. +*/ +#define ARM_MPU_AP_(RO, NP) (((RO & 1U) << 1U) | (NP & 1U)) + +/** \brief Region Base Address Register value +* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned. +* \param SH Defines the Shareability domain for this memory region. +* \param RO Read-Only: Set to 1 for a read-only memory region. +* \param NP Non-Privileged: Set to 1 for a non-privileged memory region. +* \oaram XN eXecute Never: Set to 1 for a non-executable memory region. +*/ +#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \ + ((BASE & MPU_RBAR_BASE_Msk) | \ + ((SH << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \ + ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \ + ((XN << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk)) + +/** \brief Region Limit Address Register value +* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. +* \param IDX The attribute index to be associated with this memory region. +*/ +#define ARM_MPU_RLAR(LIMIT, IDX) \ + ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ + ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ + (MPU_RLAR_EN_Msk)) + +#if defined(MPU_RLAR_PXN_Pos) + +/** \brief Region Limit Address Register with PXN value +* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended. +* \param PXN Privileged execute never. Defines whether code can be executed from this privileged region. +* \param IDX The attribute index to be associated with this memory region. +*/ +#define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \ + ((LIMIT & MPU_RLAR_LIMIT_Msk) | \ + ((PXN << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \ + ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \ + (MPU_RLAR_EN_Msk)) + +#endif + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; /*!< Region Base Address Register value */ + uint32_t RLAR; /*!< Region Limit Address Register value */ +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +#ifdef MPU_NS +/** Enable the Non-secure MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control) +{ + MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the Non-secure MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable_NS(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} +#endif + +/** Set the memory attribute encoding to the given MPU. +* \param mpu Pointer to the MPU to be configured. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr) +{ + const uint8_t reg = idx / 4U; + const uint32_t pos = ((idx % 4U) * 8U); + const uint32_t mask = 0xFFU << pos; + + if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) { + return; // invalid index + } + + mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask)); +} + +/** Set the memory attribute encoding. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr) +{ + ARM_MPU_SetMemAttrEx(MPU, idx, attr); +} + +#ifdef MPU_NS +/** Set the memory attribute encoding to the Non-secure MPU. +* \param idx The attribute index to be set [0-7] +* \param attr The attribute value to be set. +*/ +__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr) +{ + ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr); +} +#endif + +/** Clear and disable the given MPU region of the given MPU. +* \param mpu Pointer to MPU to be used. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr) +{ + mpu->RNR = rnr; + mpu->RLAR = 0U; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + ARM_MPU_ClrRegionEx(MPU, rnr); +} + +#ifdef MPU_NS +/** Clear and disable the given Non-secure MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr) +{ + ARM_MPU_ClrRegionEx(MPU_NS, rnr); +} +#endif + +/** Configure the given MPU region of the given MPU. +* \param mpu Pointer to MPU to be used. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + mpu->RNR = rnr; + mpu->RBAR = rbar; + mpu->RLAR = rlar; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar); +} + +#ifdef MPU_NS +/** Configure the given Non-secure MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rlar Value for RLAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar) +{ + ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar); +} +#endif + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table to the given MPU. +* \param mpu Pointer to the MPU registers to be used. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + if (cnt == 1U) { + mpu->RNR = rnr; + ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize); + } else { + uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U); + uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES; + + mpu->RNR = rnrBase; + while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) { + uint32_t c = MPU_TYPE_RALIASES - rnrOffset; + ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize); + table += c; + cnt -= c; + rnrOffset = 0U; + rnrBase += MPU_TYPE_RALIASES; + mpu->RNR = rnrBase; + } + + ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize); + } +} + +/** Load the given number of MPU regions from a table. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + ARM_MPU_LoadEx(MPU, rnr, table, cnt); +} + +#ifdef MPU_NS +/** Load the given number of MPU regions from a table to the Non-secure MPU. +* \param rnr First region number to be configured. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt) +{ + ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt); +} +#endif + +#endif + diff --git a/Drivers/CMSIS/Include/tz_context.h b/Drivers/CMSIS/Include/tz_context.h new file mode 100644 index 0000000..0d09749 --- /dev/null +++ b/Drivers/CMSIS/Include/tz_context.h @@ -0,0 +1,70 @@ +/****************************************************************************** + * @file tz_context.h + * @brief Context Management for Armv8-M TrustZone + * @version V1.0.1 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2017-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef TZ_CONTEXT_H +#define TZ_CONTEXT_H + +#include + +#ifndef TZ_MODULEID_T +#define TZ_MODULEID_T +/// \details Data type that identifies secure software modules called by a process. +typedef uint32_t TZ_ModuleId_t; +#endif + +/// \details TZ Memory ID identifies an allocated memory slot. +typedef uint32_t TZ_MemoryId_t; + +/// Initialize secure context memory system +/// \return execution status (1: success, 0: error) +uint32_t TZ_InitContextSystem_S (void); + +/// Allocate context memory for calling secure software modules in TrustZone +/// \param[in] module identifies software modules called from non-secure mode +/// \return value != 0 id TrustZone memory slot identifier +/// \return value 0 no memory available or internal error +TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module); + +/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id); + +/// Load secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_LoadContext_S (TZ_MemoryId_t id); + +/// Store secure context (called on RTOS thread context switch) +/// \param[in] id TrustZone memory slot identifier +/// \return execution status (1: success, 0: error) +uint32_t TZ_StoreContext_S (TZ_MemoryId_t id); + +#endif // TZ_CONTEXT_H diff --git a/Drivers/CMSIS/LICENSE.txt b/Drivers/CMSIS/LICENSE.txt new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/Drivers/CMSIS/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_adc.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_adc.h new file mode 100644 index 0000000..0765e7c --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_adc.h @@ -0,0 +1,8244 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 STM32L4xx_LL_ADC_H +#define STM32L4xx_LL_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_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_SQRX_REGOFFSET_POS (8UL) /* Position of bits ADC_SQRx_REGOFFSET in ADC_REG_SQRX_REGOFFSET_MASK*/ +#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 ( 6UL) /* Equivalent to bitfield "ADC_SQR1_SQ1" position in register */ +#define ADC_REG_RANK_2_SQRX_BITOFFSET_POS (12UL) /* Equivalent to bitfield "ADC_SQR1_SQ2" position in register */ +#define ADC_REG_RANK_3_SQRX_BITOFFSET_POS (18UL) /* Equivalent to bitfield "ADC_SQR1_SQ3" position in register */ +#define ADC_REG_RANK_4_SQRX_BITOFFSET_POS (24UL) /* Equivalent to bitfield "ADC_SQR1_SQ4" position in register */ +#define ADC_REG_RANK_5_SQRX_BITOFFSET_POS ( 0UL) /* Equivalent to bitfield "ADC_SQR2_SQ5" position in register */ +#define ADC_REG_RANK_6_SQRX_BITOFFSET_POS ( 6UL) /* Equivalent to bitfield "ADC_SQR2_SQ6" position in register */ +#define ADC_REG_RANK_7_SQRX_BITOFFSET_POS (12UL) /* Equivalent to bitfield "ADC_SQR2_SQ7" position in register */ +#define ADC_REG_RANK_8_SQRX_BITOFFSET_POS (18UL) /* Equivalent to bitfield "ADC_SQR2_SQ8" position in register */ +#define ADC_REG_RANK_9_SQRX_BITOFFSET_POS (24UL) /* Equivalent to bitfield "ADC_SQR2_SQ9" position in register */ +#define ADC_REG_RANK_10_SQRX_BITOFFSET_POS ( 0UL) /* Equivalent to bitfield "ADC_SQR3_SQ10" position in register */ +#define ADC_REG_RANK_11_SQRX_BITOFFSET_POS ( 6UL) /* Equivalent to bitfield "ADC_SQR3_SQ11" position in register */ +#define ADC_REG_RANK_12_SQRX_BITOFFSET_POS (12UL) /* Equivalent to bitfield "ADC_SQR3_SQ12" position in register */ +#define ADC_REG_RANK_13_SQRX_BITOFFSET_POS (18UL) /* Equivalent to bitfield "ADC_SQR3_SQ13" position in register */ +#define ADC_REG_RANK_14_SQRX_BITOFFSET_POS (24UL) /* Equivalent to bitfield "ADC_SQR3_SQ14" position in register */ +#define ADC_REG_RANK_15_SQRX_BITOFFSET_POS ( 0UL) /* Equivalent to bitfield "ADC_SQR4_SQ15" position in register */ +#define ADC_REG_RANK_16_SQRX_BITOFFSET_POS ( 6UL) /* Equivalent to bitfield "ADC_SQR4_SQ16" position in register */ + + + +/* Internal mask for ADC group injected sequencer: */ +/* To select into literal LL_ADC_INJ_RANK_x the relevant bits for: */ +/* - data 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) + +#define ADC_INJ_JDRX_REGOFFSET_MASK (ADC_JDR1_REGOFFSET | ADC_JDR2_REGOFFSET \ + | ADC_JDR3_REGOFFSET | ADC_JDR4_REGOFFSET) +#define ADC_INJ_RANK_ID_JSQR_MASK (ADC_CHANNEL_ID_NUMBER_MASK_POSBIT0) +#define ADC_JDRX_REGOFFSET_POS (8UL) /* Position of bits ADC_JDRx_REGOFFSET in ADC_INJ_JDRX_REGOFFSET_MASK*/ + +/* Definition of ADC group injected sequencer bits information to be inserted */ +/* into ADC group injected sequencer ranks literals definition. */ +#define ADC_INJ_RANK_1_JSQR_BITOFFSET_POS ( 8UL) /* Equivalent to bitfield "ADC_JSQR_JSQ1" position in register */ +#define ADC_INJ_RANK_2_JSQR_BITOFFSET_POS (14UL) /* Equivalent to bitfield "ADC_JSQR_JSQ2" position in register */ +#define ADC_INJ_RANK_3_JSQR_BITOFFSET_POS (20UL) /* Equivalent to bitfield "ADC_JSQR_JSQ3" position in register */ +#define ADC_INJ_RANK_4_JSQR_BITOFFSET_POS (26UL) /* Equivalent to bitfield "ADC_JSQR_JSQ4" position in register */ + + + +/* 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_CFGR_EXTEN_0) /* Trigger edge set to rising edge (default setting for + compatibility with some ADC on other STM32 series + 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_CFGR_EXTSEL) << (4U * 0UL)) | \ + ((ADC_CFGR_EXTSEL) << (4U * 1UL)) | \ + ((ADC_CFGR_EXTSEL) << (4U * 2UL)) | \ + ((ADC_CFGR_EXTSEL) << (4U * 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_CFGR_EXTEN) << (4U * 0UL)) | \ + ((ADC_REG_TRIG_EXT_EDGE_DEFAULT) << (4U * 1UL)) | \ + ((ADC_REG_TRIG_EXT_EDGE_DEFAULT) << (4U * 2UL)) | \ + ((ADC_REG_TRIG_EXT_EDGE_DEFAULT) << (4U * 3UL)) ) + +/* Definition of ADC group regular trigger bits information. */ +#define ADC_REG_TRIG_EXTSEL_BITOFFSET_POS ( 6UL) /* Equivalent to bitfield "ADC_CFGR_EXTSEL" position in register */ +#define ADC_REG_TRIG_EXTEN_BITOFFSET_POS (10UL) /* Equivalent to bitfield "ADC_CFGR_EXTEN" position in register */ + + + +/* 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_JSQR_JEXTEN_0) /* Trigger edge set to rising edge (default setting for + compatibility with some ADC on other STM32 series + 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_INJ_TRIG_SOFTWARE & ADC_JSQR_JEXTSEL) << (4U * 0UL)) | \ + ((ADC_JSQR_JEXTSEL) << (4U * 1UL)) | \ + ((ADC_JSQR_JEXTSEL) << (4U * 2UL)) | \ + ((ADC_JSQR_JEXTSEL) << (4U * 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_JSQR_JEXTEN) << (4U * 0UL)) | \ + ((ADC_INJ_TRIG_EXT_EDGE_DEFAULT) << (4U * 1UL)) | \ + ((ADC_INJ_TRIG_EXT_EDGE_DEFAULT) << (4U * 2UL)) | \ + ((ADC_INJ_TRIG_EXT_EDGE_DEFAULT) << (4U * 3UL)) ) + +/* Definition of ADC group injected trigger bits information. */ +#define ADC_INJ_TRIG_EXTSEL_BITOFFSET_POS ( 2UL) /* Equivalent to bitfield "ADC_JSQR_JEXTSEL" position in register */ +#define ADC_INJ_TRIG_EXTEN_BITOFFSET_POS ( 6UL) /* Equivalent to bitfield "ADC_JSQR_JEXTEN" position in register */ + + + + + + +/* Internal mask for ADC channel: */ +/* To select into literal LL_ADC_CHANNEL_x the relevant bits for: */ +/* - channel identifier defined by number */ +/* - channel identifier defined by bitfield */ +/* - 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_CFGR_AWD1CH) +#define ADC_CHANNEL_ID_BITFIELD_MASK (ADC_AWD2CR_AWD2CH) +#define ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS (26UL) /* Equivalent to bitfield "ADC_CHANNEL_ID_NUMBER_MASK" + position in register */ +#define ADC_CHANNEL_ID_MASK (ADC_CHANNEL_ID_NUMBER_MASK | ADC_CHANNEL_ID_BITFIELD_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 (ADC_SQR2_SQ5) /* Equivalent to shift: (ADC_CHANNEL_NUMBER_MASK + >> [Position of bitfield "ADC_CHANNEL_NUMBER_MASK" in register]) */ + +/* 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 (0x00080000UL) /* 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_ID_INTERNAL_CH_MASK (ADC_CHANNEL_ID_INTERNAL_CH | ADC_CHANNEL_ID_INTERNAL_CH_2) + +/* 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_SMPRX_REGOFFSET_POS (25UL) /* Position of bits ADC_SMPRx_REGOFFSET + in ADC_CHANNEL_SMPRX_REGOFFSET_MASK */ + +#define ADC_CHANNEL_SMPx_BITOFFSET_MASK (0x01F00000UL) +#define ADC_CHANNEL_SMPx_BITOFFSET_POS (20UL) /* Equivalent to bitfield "ADC_CHANNEL_SMPx_BITOFFSET_MASK" + position in register */ + +/* 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_CFGR_AWD1CH_0) +#define ADC_CHANNEL_2_NUMBER (ADC_CFGR_AWD1CH_1) +#define ADC_CHANNEL_3_NUMBER (ADC_CFGR_AWD1CH_1 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_4_NUMBER (ADC_CFGR_AWD1CH_2) +#define ADC_CHANNEL_5_NUMBER (ADC_CFGR_AWD1CH_2 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_6_NUMBER (ADC_CFGR_AWD1CH_2 | ADC_CFGR_AWD1CH_1) +#define ADC_CHANNEL_7_NUMBER (ADC_CFGR_AWD1CH_2 | ADC_CFGR_AWD1CH_1 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_8_NUMBER (ADC_CFGR_AWD1CH_3) +#define ADC_CHANNEL_9_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_10_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_1) +#define ADC_CHANNEL_11_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_1 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_12_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_2) +#define ADC_CHANNEL_13_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_2 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_14_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_2 | ADC_CFGR_AWD1CH_1) +#define ADC_CHANNEL_15_NUMBER (ADC_CFGR_AWD1CH_3 | ADC_CFGR_AWD1CH_2 | \ + ADC_CFGR_AWD1CH_1 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_16_NUMBER (ADC_CFGR_AWD1CH_4) +#define ADC_CHANNEL_17_NUMBER (ADC_CFGR_AWD1CH_4 | ADC_CFGR_AWD1CH_0) +#define ADC_CHANNEL_18_NUMBER (ADC_CFGR_AWD1CH_4 | ADC_CFGR_AWD1CH_1) + +/* Definition of channels ID bitfield information to be inserted into */ +/* channels literals definition. */ +#define ADC_CHANNEL_0_BITFIELD (ADC_AWD2CR_AWD2CH_0) +#define ADC_CHANNEL_1_BITFIELD (ADC_AWD2CR_AWD2CH_1) +#define ADC_CHANNEL_2_BITFIELD (ADC_AWD2CR_AWD2CH_2) +#define ADC_CHANNEL_3_BITFIELD (ADC_AWD2CR_AWD2CH_3) +#define ADC_CHANNEL_4_BITFIELD (ADC_AWD2CR_AWD2CH_4) +#define ADC_CHANNEL_5_BITFIELD (ADC_AWD2CR_AWD2CH_5) +#define ADC_CHANNEL_6_BITFIELD (ADC_AWD2CR_AWD2CH_6) +#define ADC_CHANNEL_7_BITFIELD (ADC_AWD2CR_AWD2CH_7) +#define ADC_CHANNEL_8_BITFIELD (ADC_AWD2CR_AWD2CH_8) +#define ADC_CHANNEL_9_BITFIELD (ADC_AWD2CR_AWD2CH_9) +#define ADC_CHANNEL_10_BITFIELD (ADC_AWD2CR_AWD2CH_10) +#define ADC_CHANNEL_11_BITFIELD (ADC_AWD2CR_AWD2CH_11) +#define ADC_CHANNEL_12_BITFIELD (ADC_AWD2CR_AWD2CH_12) +#define ADC_CHANNEL_13_BITFIELD (ADC_AWD2CR_AWD2CH_13) +#define ADC_CHANNEL_14_BITFIELD (ADC_AWD2CR_AWD2CH_14) +#define ADC_CHANNEL_15_BITFIELD (ADC_AWD2CR_AWD2CH_15) +#define ADC_CHANNEL_16_BITFIELD (ADC_AWD2CR_AWD2CH_16) +#define ADC_CHANNEL_17_BITFIELD (ADC_AWD2CR_AWD2CH_17) +#define ADC_CHANNEL_18_BITFIELD (ADC_AWD2CR_AWD2CH_18) + +/* Definition of channels sampling time information to be inserted into */ +/* channels literals definition. */ +/* Value shifted are equivalent to bitfield "ADC_SMPRx_SMPy" position */ +/* in register. */ +#define ADC_CHANNEL_0_SMP (ADC_SMPR1_REGOFFSET | (( 0UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_1_SMP (ADC_SMPR1_REGOFFSET | (( 3UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_2_SMP (ADC_SMPR1_REGOFFSET | (( 6UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_3_SMP (ADC_SMPR1_REGOFFSET | (( 9UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_4_SMP (ADC_SMPR1_REGOFFSET | ((12UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_5_SMP (ADC_SMPR1_REGOFFSET | ((15UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_6_SMP (ADC_SMPR1_REGOFFSET | ((18UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_7_SMP (ADC_SMPR1_REGOFFSET | ((21UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_8_SMP (ADC_SMPR1_REGOFFSET | ((24UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_9_SMP (ADC_SMPR1_REGOFFSET | ((27UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_10_SMP (ADC_SMPR2_REGOFFSET | (( 0UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_11_SMP (ADC_SMPR2_REGOFFSET | (( 3UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_12_SMP (ADC_SMPR2_REGOFFSET | (( 6UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_13_SMP (ADC_SMPR2_REGOFFSET | (( 9UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_14_SMP (ADC_SMPR2_REGOFFSET | ((12UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_15_SMP (ADC_SMPR2_REGOFFSET | ((15UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_16_SMP (ADC_SMPR2_REGOFFSET | ((18UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_17_SMP (ADC_SMPR2_REGOFFSET | ((21UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) +#define ADC_CHANNEL_18_SMP (ADC_SMPR2_REGOFFSET | ((24UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) + + +/* Internal mask for ADC mode single or differential ended: */ +/* To select into literals LL_ADC_SINGLE_ENDED or LL_ADC_SINGLE_DIFFERENTIAL */ +/* the relevant bits for: */ +/* (concatenation of multiple bits used in different registers) */ +/* - ADC calibration: calibration start, calibration factor get or set */ +/* - ADC channels: set each ADC channel ending mode */ +#define ADC_SINGLEDIFF_CALIB_START_MASK (ADC_CR_ADCALDIF) +#define ADC_SINGLEDIFF_CALIB_FACTOR_MASK (ADC_CALFACT_CALFACT_D | ADC_CALFACT_CALFACT_S) +#define ADC_SINGLEDIFF_CHANNEL_MASK (ADC_CHANNEL_ID_BITFIELD_MASK) /* Equivalent to ADC_DIFSEL_DIFSEL */ +#define ADC_SINGLEDIFF_CHANNEL_SHIFT_MASK (ADC_CALFACT_CALFACT_S_4 | ADC_CALFACT_CALFACT_S_3) /* Bits chosen + to perform of shift when single mode is selected, shift value out of + channels bits range. */ +#define ADC_SINGLEDIFF_CALIB_F_BIT_D_MASK (0x00010000UL) /* Selection of 1 bit to discriminate differential mode: + mask of bit */ +#define ADC_SINGLEDIFF_CALIB_F_BIT_D_POS (16UL) /* Selection of 1 bit to discriminate differential mode: + position of bit */ +#define ADC_SINGLEDIFF_CALIB_F_BIT_D_SHIFT4 (ADC_SINGLEDIFF_CALIB_F_BIT_D_POS - 4UL) /* Shift of bit + ADC_SINGLEDIFF_CALIB_F_BIT_D to perform a shift of 4 ranks */ + +/* 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 series)). */ +/* - analog watchdog 1: monitored channel defined by number, */ +/* selection of ADC group (ADC groups regular and-or injected). */ +/* - analog watchdog 2 and 3: monitored channel defined by bitfield, no */ +/* selection on groups. */ + +/* Internal register offset for ADC analog watchdog channel configuration */ +#define ADC_AWD_CR1_REGOFFSET (0x00000000UL) +#define ADC_AWD_CR2_REGOFFSET (0x00100000UL) +#define ADC_AWD_CR3_REGOFFSET (0x00200000UL) + +/* Register offset gap between AWD1 and AWD2-AWD3 configuration registers */ +/* (Set separately as ADC_AWD_CRX_REGOFFSET to spare 32 bits space */ +#define ADC_AWD_CR12_REGOFFSETGAP_MASK (ADC_AWD2CR_AWD2CH_0) +#define ADC_AWD_CR12_REGOFFSETGAP_VAL (0x00000024UL) + +#define ADC_AWD_CRX_REGOFFSET_MASK (ADC_AWD_CR1_REGOFFSET | ADC_AWD_CR2_REGOFFSET | ADC_AWD_CR3_REGOFFSET) + +#define ADC_AWD_CR1_CHANNEL_MASK (ADC_CFGR_AWD1CH | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) +#define ADC_AWD_CR23_CHANNEL_MASK (ADC_AWD2CR_AWD2CH) +#define ADC_AWD_CR_ALL_CHANNEL_MASK (ADC_AWD_CR1_CHANNEL_MASK | ADC_AWD_CR23_CHANNEL_MASK) + +#define ADC_AWD_CRX_REGOFFSET_POS (20UL) /* Position of bits ADC_AWD_CRx_REGOFFSET + in ADC_AWD_CRX_REGOFFSET_MASK */ + +/* Internal register offset for ADC analog watchdog threshold configuration */ +#define ADC_AWD_TR1_REGOFFSET (ADC_AWD_CR1_REGOFFSET) +#define ADC_AWD_TR2_REGOFFSET (ADC_AWD_CR2_REGOFFSET) +#define ADC_AWD_TR3_REGOFFSET (ADC_AWD_CR3_REGOFFSET) +#define ADC_AWD_TRX_REGOFFSET_MASK (ADC_AWD_TR1_REGOFFSET | ADC_AWD_TR2_REGOFFSET | ADC_AWD_TR3_REGOFFSET) +#define ADC_AWD_TRX_REGOFFSET_POS (ADC_AWD_CRX_REGOFFSET_POS) /* Position of bits ADC_SQRx_REGOFFSET + in ADC_AWD_TRX_REGOFFSET_MASK */ +#define ADC_AWD_TRX_BIT_HIGH_MASK (0x00010000UL) /* Selection of 1 bit to discriminate + threshold high: mask of bit */ +#define ADC_AWD_TRX_BIT_HIGH_POS (16UL) /* Selection of 1 bit to discriminate + threshold high: position of bit */ +#define ADC_AWD_TRX_BIT_HIGH_SHIFT4 (ADC_AWD_TRX_BIT_HIGH_POS - 4UL) /* Shift of bit ADC_AWD_TRX_BIT_HIGH to + position to perform a shift of 4 ranks */ + +/* Internal mask for ADC offset: */ +/* Internal register offset for ADC offset instance configuration */ +#define ADC_OFR1_REGOFFSET (0x00000000UL) +#define ADC_OFR2_REGOFFSET (0x00000001UL) +#define ADC_OFR3_REGOFFSET (0x00000002UL) +#define ADC_OFR4_REGOFFSET (0x00000003UL) +#define ADC_OFRx_REGOFFSET_MASK (ADC_OFR1_REGOFFSET | ADC_OFR2_REGOFFSET \ + | ADC_OFR3_REGOFFSET | ADC_OFR4_REGOFFSET) + + +/* ADC registers bits positions */ +#define ADC_CFGR_RES_BITOFFSET_POS ( 3UL) /* Equivalent to bitfield "ADC_CFGR_RES" position in register */ +#define ADC_CFGR_AWD1SGL_BITOFFSET_POS (22UL) /* Equivalent to bitfield "ADC_CFGR_AWD1SGL" position in register */ +#define ADC_CFGR_AWD1EN_BITOFFSET_POS (23UL) /* Equivalent to bitfield "ADC_CFGR_AWD1EN" position in register */ +#define ADC_CFGR_JAWD1EN_BITOFFSET_POS (24UL) /* Equivalent to bitfield "ADC_CFGR_JAWD1EN" position in register */ +#define ADC_TR1_HT1_BITOFFSET_POS (16UL) /* Equivalent to bitfield "ADC_TR1_HT1" position in register */ + + +/* ADC registers bits groups */ +#define ADC_CR_BITS_PROPERTY_RS (ADC_CR_ADCAL | ADC_CR_ADEN | ADC_CR_ADDIS \ + | ADC_CR_JADSTART | ADC_CR_JADSTP \ + | ADC_CR_ADSTART | ADC_CR_ADSTP) /* ADC register CR bits with + HW property "rs": Software can read as well as set this bit. + Writing '0' has no effect on the bit value. */ + + +/* ADC internal channels related definitions */ +/* Internal voltage reference VrefInt */ +#define VREFINT_CAL_ADDR ((uint16_t*) (0x1FFF75AAUL)) /* Internal voltage reference, address of + parameter VREFINT_CAL: VrefInt ADC raw data acquired at temperature 30 DegC + (tolerance: +-5 DegC), Vref+ = 3.0 V (tolerance: +-10 mV). */ +#define VREFINT_CAL_VREF ( 3000UL) /* Analog voltage reference (Vref+) value + with which VrefInt has been calibrated in production + (tolerance: +-10 mV) (unit: mV). */ +/* Temperature sensor */ +#define TEMPSENSOR_CAL1_ADDR ((uint16_t*) (0x1FFF75A8UL)) /* Address of parameter TS_CAL1: On STM32L4, + temperature sensor ADC raw data acquired at temperature 30 DegC + (tolerance: +-5 DegC), Vref+ = 3.0 V (tolerance: +-10 mV). */ +#define TEMPSENSOR_CAL2_ADDR ((uint16_t*) (0x1FFF75CAUL)) /* Address of parameter TS_CAL2: On STM32L4, + temperature sensor ADC raw data acquired at temperature defined by + TEMPSENSOR_CAL2_TEMP (tolerance: +-5 DegC), Vref+ = 3.0 V (tolerance: +-10 mV). */ +#define TEMPSENSOR_CAL1_TEMP (( int32_t) 30L) /* Temperature at which temperature sensor + has been calibrated in production for data into TEMPSENSOR_CAL1_ADDR + (tolerance: +-5 DegC) (unit: DegC). */ +#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) +#define TEMPSENSOR_CAL2_TEMP (110L) /* Temperature at which temperature sensor + has been calibrated in production for data into TEMPSENSOR_CAL2_ADDR + (tolerance: +-5 DegC) (unit: DegC). */ +#else +#define TEMPSENSOR_CAL2_TEMP (130L) /* Temperature at which temperature sensor + has been calibrated in production for data into TEMPSENSOR_CAL2_ADDR + (tolerance: +-5 DegC) (unit: DegC). */ +#endif /* defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) */ +#define TEMPSENSOR_CAL_VREFANALOG (3000UL) /* Analog voltage reference (Vref+) value + with which temperature sensor has been calibrated in production + (tolerance +-10 mV) (unit: mV). */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ADC_LL_Private_Macros ADC Private Macros + * @{ + */ + +/** + * @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 + @note On this STM32 series, if ADC group injected is used, some clock ratio + constraints between ADC clock and AHB clock must be respected. + Refer to reference manual. + 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 series). + * 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 series. 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 LowPowerMode; /*!< Set ADC low power mode. + This parameter can be a value of @ref ADC_LL_EC_LP_MODE + This feature can be modified afterwards using unitary function + @ref LL_ADC_SetLowPowerMode(). */ + +} 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 series. 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 peripheral (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 trigger source to external trigger also + set trigger polarity to rising edge(default setting for compatibility + with some ADC on other STM32 series having this setting set by HW + default value). + In case of need to modify trigger edge, use function + @ref LL_ADC_REG_SetTriggerEdge(). + 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 + 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(). */ + + uint32_t Overrun; /*!< Set ADC group regular behavior in case of overrun: + data preserved or overwritten. + This parameter can be a value of @ref ADC_LL_EC_REG_OVR_DATA_BEHAVIOR + This feature can be modified afterwards using unitary function + @ref LL_ADC_REG_SetOverrun(). */ + +} 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 series. 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 peripheral (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 trigger source to external trigger also + set trigger polarity to rising edge (default setting for + compatibility with some ADC on other STM32 series having this + setting set by HW default value). + In case of need to modify trigger edge, use function + @ref LL_ADC_INJ_SetTriggerEdge(). + 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 + 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_ADRDY ADC_ISR_ADRDY /*!< ADC flag ADC instance ready */ +#define LL_ADC_FLAG_EOC ADC_ISR_EOC /*!< ADC flag ADC group regular end of unitary + conversion */ +#define LL_ADC_FLAG_EOS ADC_ISR_EOS /*!< ADC flag ADC group regular end of sequence + conversions */ +#define LL_ADC_FLAG_OVR ADC_ISR_OVR /*!< ADC flag ADC group regular overrun */ +#define LL_ADC_FLAG_EOSMP ADC_ISR_EOSMP /*!< ADC flag ADC group regular end of sampling phase */ +#define LL_ADC_FLAG_JEOC ADC_ISR_JEOC /*!< ADC flag ADC group injected end of unitary + conversion */ +#define LL_ADC_FLAG_JEOS ADC_ISR_JEOS /*!< ADC flag ADC group injected end of sequence + conversions */ +#define LL_ADC_FLAG_JQOVF ADC_ISR_JQOVF /*!< ADC flag ADC group injected contexts queue + overflow */ +#define LL_ADC_FLAG_AWD1 ADC_ISR_AWD1 /*!< ADC flag ADC analog watchdog 1 */ +#define LL_ADC_FLAG_AWD2 ADC_ISR_AWD2 /*!< ADC flag ADC analog watchdog 2 */ +#define LL_ADC_FLAG_AWD3 ADC_ISR_AWD3 /*!< ADC flag ADC analog watchdog 3 */ +#if defined(ADC_MULTIMODE_SUPPORT) +#define LL_ADC_FLAG_ADRDY_MST ADC_CSR_ADRDY_MST /*!< ADC flag ADC multimode master instance ready */ +#define LL_ADC_FLAG_ADRDY_SLV ADC_CSR_ADRDY_SLV /*!< ADC flag ADC multimode slave instance ready */ +#define LL_ADC_FLAG_EOC_MST ADC_CSR_EOC_MST /*!< ADC flag ADC multimode master group regular end of + unitary conversion */ +#define LL_ADC_FLAG_EOC_SLV ADC_CSR_EOC_SLV /*!< ADC flag ADC multimode slave group regular end of + unitary conversion */ +#define LL_ADC_FLAG_EOS_MST ADC_CSR_EOS_MST /*!< ADC flag ADC multimode master group regular end of + sequence conversions */ +#define LL_ADC_FLAG_EOS_SLV ADC_CSR_EOS_SLV /*!< ADC flag ADC multimode slave group regular end of + sequence conversions */ +#define LL_ADC_FLAG_OVR_MST ADC_CSR_OVR_MST /*!< ADC flag ADC multimode master group regular + overrun */ +#define LL_ADC_FLAG_OVR_SLV ADC_CSR_OVR_SLV /*!< ADC flag ADC multimode slave group regular + overrun */ +#define LL_ADC_FLAG_EOSMP_MST ADC_CSR_EOSMP_MST /*!< ADC flag ADC multimode master group regular end of + sampling phase */ +#define LL_ADC_FLAG_EOSMP_SLV ADC_CSR_EOSMP_SLV /*!< ADC flag ADC multimode slave group regular end of + sampling phase */ +#define LL_ADC_FLAG_JEOC_MST ADC_CSR_JEOC_MST /*!< ADC flag ADC multimode master group injected end of + unitary conversion */ +#define LL_ADC_FLAG_JEOC_SLV ADC_CSR_JEOC_SLV /*!< ADC flag ADC multimode slave group injected end of + unitary conversion */ +#define LL_ADC_FLAG_JEOS_MST ADC_CSR_JEOS_MST /*!< ADC flag ADC multimode master group injected end of + sequence conversions */ +#define LL_ADC_FLAG_JEOS_SLV ADC_CSR_JEOS_SLV /*!< ADC flag ADC multimode slave group injected end of + sequence conversions */ +#define LL_ADC_FLAG_JQOVF_MST ADC_CSR_JQOVF_MST /*!< ADC flag ADC multimode master group injected + contexts queue overflow */ +#define LL_ADC_FLAG_JQOVF_SLV ADC_CSR_JQOVF_SLV /*!< ADC flag ADC multimode slave group injected + contexts queue overflow */ +#define LL_ADC_FLAG_AWD1_MST ADC_CSR_AWD1_MST /*!< ADC flag ADC multimode master analog watchdog 1 + of the ADC master */ +#define LL_ADC_FLAG_AWD1_SLV ADC_CSR_AWD1_SLV /*!< ADC flag ADC multimode slave analog watchdog 1 + of the ADC slave */ +#define LL_ADC_FLAG_AWD2_MST ADC_CSR_AWD2_MST /*!< ADC flag ADC multimode master analog watchdog 2 + of the ADC master */ +#define LL_ADC_FLAG_AWD2_SLV ADC_CSR_AWD2_SLV /*!< ADC flag ADC multimode slave analog watchdog 2 + of the ADC slave */ +#define LL_ADC_FLAG_AWD3_MST ADC_CSR_AWD3_MST /*!< ADC flag ADC multimode master analog watchdog 3 + of the ADC master */ +#define LL_ADC_FLAG_AWD3_SLV ADC_CSR_AWD3_SLV /*!< ADC flag ADC multimode slave analog watchdog 3 + of the ADC slave */ +#endif /* ADC_MULTIMODE_SUPPORT */ +/** + * @} + */ + +/** @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_ADRDY ADC_IER_ADRDYIE /*!< ADC interruption ADC instance ready */ +#define LL_ADC_IT_EOC ADC_IER_EOCIE /*!< ADC interruption ADC group regular end of unitary + conversion */ +#define LL_ADC_IT_EOS ADC_IER_EOSIE /*!< ADC interruption ADC group regular end of sequence + conversions */ +#define LL_ADC_IT_OVR ADC_IER_OVRIE /*!< ADC interruption ADC group regular overrun */ +#define LL_ADC_IT_EOSMP ADC_IER_EOSMPIE /*!< ADC interruption ADC group regular end of sampling + phase */ +#define LL_ADC_IT_JEOC ADC_IER_JEOCIE /*!< ADC interruption ADC group injected end of unitary + conversion */ +#define LL_ADC_IT_JEOS ADC_IER_JEOSIE /*!< ADC interruption ADC group injected end of sequence + conversions */ +#define LL_ADC_IT_JQOVF ADC_IER_JQOVFIE /*!< ADC interruption ADC group injected contexts queue + overflow */ +#define LL_ADC_IT_AWD1 ADC_IER_AWD1IE /*!< ADC interruption ADC analog watchdog 1 */ +#define LL_ADC_IT_AWD2 ADC_IER_AWD2IE /*!< ADC interruption ADC analog watchdog 2 */ +#define LL_ADC_IT_AWD3 ADC_IER_AWD3IE /*!< ADC interruption ADC analog watchdog 3 */ +/** + * @} + */ + +/** @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 /* ADC_MULTIMODE_SUPPORT */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_COMMON_CLOCK_SOURCE ADC common - Clock source + * @{ + */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV1 (ADC_CCR_CKMODE_0) /*!< ADC synchronous clock derived from + AHB clock without prescaler */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV2 (ADC_CCR_CKMODE_1) /*!< ADC synchronous clock derived from + AHB clock with prescaler division by 2 */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV4 (ADC_CCR_CKMODE_1 | ADC_CCR_CKMODE_0) /*!< ADC synchronous clock derived from + AHB clock with prescaler division by 4 */ +#define LL_ADC_CLOCK_ASYNC_DIV1 (0x00000000UL) /*!< ADC asynchronous clock without + prescaler */ +#define LL_ADC_CLOCK_ASYNC_DIV2 (ADC_CCR_PRESC_0) /*!< ADC asynchronous clock with + prescaler division by 2 */ +#define LL_ADC_CLOCK_ASYNC_DIV4 (ADC_CCR_PRESC_1) /*!< ADC asynchronous clock with + prescaler division by 4 */ +#define LL_ADC_CLOCK_ASYNC_DIV6 (ADC_CCR_PRESC_1 | ADC_CCR_PRESC_0) /*!< ADC asynchronous clock with + prescaler division by 6 */ +#define LL_ADC_CLOCK_ASYNC_DIV8 (ADC_CCR_PRESC_2) /*!< ADC asynchronous clock with + prescaler division by 8 */ +#define LL_ADC_CLOCK_ASYNC_DIV10 (ADC_CCR_PRESC_2 | ADC_CCR_PRESC_0) /*!< ADC asynchronous clock with + prescaler division by 10 */ +#define LL_ADC_CLOCK_ASYNC_DIV12 (ADC_CCR_PRESC_2 | ADC_CCR_PRESC_1) /*!< ADC asynchronous clock with + prescaler division by 12 */ +#define LL_ADC_CLOCK_ASYNC_DIV16 (ADC_CCR_PRESC_2 | ADC_CCR_PRESC_1 \ + | ADC_CCR_PRESC_0) /*!< ADC asynchronous clock with + prescaler division by 16 */ +#define LL_ADC_CLOCK_ASYNC_DIV32 (ADC_CCR_PRESC_3) /*!< ADC asynchronous clock with + prescaler division by 32 */ +#define LL_ADC_CLOCK_ASYNC_DIV64 (ADC_CCR_PRESC_3 | ADC_CCR_PRESC_0) /*!< ADC asynchronous clock with + prescaler division by 64 */ +#define LL_ADC_CLOCK_ASYNC_DIV128 (ADC_CCR_PRESC_3 | ADC_CCR_PRESC_1) /*!< ADC asynchronous clock with + prescaler division by 128 */ +#define LL_ADC_CLOCK_ASYNC_DIV256 (ADC_CCR_PRESC_3 | ADC_CCR_PRESC_1 \ + | ADC_CCR_PRESC_0) /*!< ADC asynchronous clock with + prescaler division by 256 */ +/** + * @} + */ + +/** @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_VREFEN) /*!< ADC measurement path to internal channel VrefInt */ +#define LL_ADC_PATH_INTERNAL_TEMPSENSOR (ADC_CCR_TSEN) /*!< ADC measurement path to internal channel + temperature sensor */ +#define LL_ADC_PATH_INTERNAL_VBAT (ADC_CCR_VBATEN) /*!< 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_CFGR_RES_0) /*!< ADC resolution 10 bits */ +#define LL_ADC_RESOLUTION_8B (ADC_CFGR_RES_1 ) /*!< ADC resolution 8 bits */ +#define LL_ADC_RESOLUTION_6B (ADC_CFGR_RES_1 | ADC_CFGR_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_CFGR_ALIGN) /*!< ADC conversion data alignment: left aligned + (alignment on data register MSB bit 15)*/ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_LP_MODE ADC instance - Low power mode + * @{ + */ +#define LL_ADC_LP_MODE_NONE (0x00000000UL) /*!< No ADC low power mode activated */ +#define LL_ADC_LP_AUTOWAIT (ADC_CFGR_AUTDLY) /*!< ADC low power mode auto delay: Dynamic low power + mode, ADC conversions are performed only when necessary + (when previous ADC conversion data is read). + See description with function @ref LL_ADC_SetLowPowerMode(). */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_OFFSET_NB ADC instance - Offset instance + * @{ + */ +#define LL_ADC_OFFSET_1 ADC_OFR1_REGOFFSET /*!< ADC offset instance 1: ADC channel and offset level + to which the offset programmed will be applied (independently of channel + mapped on ADC group regular or injected) */ +#define LL_ADC_OFFSET_2 ADC_OFR2_REGOFFSET /*!< ADC offset instance 2: ADC channel and offset level + to which the offset programmed will be applied (independently of channel + mapped on ADC group regular or injected) */ +#define LL_ADC_OFFSET_3 ADC_OFR3_REGOFFSET /*!< ADC offset instance 3: ADC channel and offset level + to which the offset programmed will be applied (independently of channel + mapped on ADC group regular or injected) */ +#define LL_ADC_OFFSET_4 ADC_OFR4_REGOFFSET /*!< ADC offset instance 4: ADC channel and offset level + to which the offset programmed will be applied (independently of channel + mapped on ADC group regular or injected) */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_OFFSET_STATE ADC instance - Offset state + * @{ + */ +#define LL_ADC_OFFSET_DISABLE (0x00000000UL) /*!< ADC offset disabled + (setting offset instance wise) */ +#define LL_ADC_OFFSET_ENABLE (ADC_OFR1_OFFSET1_EN) /*!< ADC offset enabled + (setting offset instance wise) */ +/** + * @} + */ + +/** @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_CHANNEL_0_BITFIELD) /*!< ADC channel ADCx_IN0 */ +#define LL_ADC_CHANNEL_1 (ADC_CHANNEL_1_NUMBER | ADC_CHANNEL_1_SMP \ + | ADC_CHANNEL_1_BITFIELD) /*!< ADC channel ADCx_IN1 */ +#define LL_ADC_CHANNEL_2 (ADC_CHANNEL_2_NUMBER | ADC_CHANNEL_2_SMP \ + | ADC_CHANNEL_2_BITFIELD) /*!< ADC channel ADCx_IN2 */ +#define LL_ADC_CHANNEL_3 (ADC_CHANNEL_3_NUMBER | ADC_CHANNEL_3_SMP \ + | ADC_CHANNEL_3_BITFIELD) /*!< ADC channel ADCx_IN3 */ +#define LL_ADC_CHANNEL_4 (ADC_CHANNEL_4_NUMBER | ADC_CHANNEL_4_SMP \ + | ADC_CHANNEL_4_BITFIELD) /*!< ADC channel ADCx_IN4 */ +#define LL_ADC_CHANNEL_5 (ADC_CHANNEL_5_NUMBER | ADC_CHANNEL_5_SMP \ + | ADC_CHANNEL_5_BITFIELD) /*!< ADC channel ADCx_IN5 */ +#define LL_ADC_CHANNEL_6 (ADC_CHANNEL_6_NUMBER | ADC_CHANNEL_6_SMP \ + | ADC_CHANNEL_6_BITFIELD) /*!< ADC channel ADCx_IN6 */ +#define LL_ADC_CHANNEL_7 (ADC_CHANNEL_7_NUMBER | ADC_CHANNEL_7_SMP \ + | ADC_CHANNEL_7_BITFIELD) /*!< ADC channel ADCx_IN7 */ +#define LL_ADC_CHANNEL_8 (ADC_CHANNEL_8_NUMBER | ADC_CHANNEL_8_SMP \ + | ADC_CHANNEL_8_BITFIELD) /*!< ADC channel ADCx_IN8 */ +#define LL_ADC_CHANNEL_9 (ADC_CHANNEL_9_NUMBER | ADC_CHANNEL_9_SMP \ + | ADC_CHANNEL_9_BITFIELD) /*!< ADC channel ADCx_IN9 */ +#define LL_ADC_CHANNEL_10 (ADC_CHANNEL_10_NUMBER | ADC_CHANNEL_10_SMP \ + | ADC_CHANNEL_10_BITFIELD) /*!< ADC channel ADCx_IN10 */ +#define LL_ADC_CHANNEL_11 (ADC_CHANNEL_11_NUMBER | ADC_CHANNEL_11_SMP \ + | ADC_CHANNEL_11_BITFIELD) /*!< ADC channel ADCx_IN11 */ +#define LL_ADC_CHANNEL_12 (ADC_CHANNEL_12_NUMBER | ADC_CHANNEL_12_SMP \ + | ADC_CHANNEL_12_BITFIELD) /*!< ADC channel ADCx_IN12 */ +#define LL_ADC_CHANNEL_13 (ADC_CHANNEL_13_NUMBER | ADC_CHANNEL_13_SMP \ + | ADC_CHANNEL_13_BITFIELD) /*!< ADC channel ADCx_IN13 */ +#define LL_ADC_CHANNEL_14 (ADC_CHANNEL_14_NUMBER | ADC_CHANNEL_14_SMP \ + | ADC_CHANNEL_14_BITFIELD) /*!< ADC channel ADCx_IN14 */ +#define LL_ADC_CHANNEL_15 (ADC_CHANNEL_15_NUMBER | ADC_CHANNEL_15_SMP \ + | ADC_CHANNEL_15_BITFIELD) /*!< ADC channel ADCx_IN15 */ +#define LL_ADC_CHANNEL_16 (ADC_CHANNEL_16_NUMBER | ADC_CHANNEL_16_SMP | \ + ADC_CHANNEL_16_BITFIELD) /*!< ADC channel ADCx_IN16 */ +#define LL_ADC_CHANNEL_17 (ADC_CHANNEL_17_NUMBER | ADC_CHANNEL_17_SMP | \ + ADC_CHANNEL_17_BITFIELD) /*!< ADC channel ADCx_IN17 */ +#define LL_ADC_CHANNEL_18 (ADC_CHANNEL_18_NUMBER | ADC_CHANNEL_18_SMP | \ + ADC_CHANNEL_18_BITFIELD) /*!< ADC channel ADCx_IN18 */ +#define LL_ADC_CHANNEL_VREFINT (LL_ADC_CHANNEL_0 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel + connected to VrefInt: Internal voltage reference. + On STM32L4, ADC channel available only on ADC instance: ADC1. */ +#define LL_ADC_CHANNEL_TEMPSENSOR (LL_ADC_CHANNEL_17 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel + connected to internal temperature sensor. + On STM32L4, ADC channel available only on ADC instances: ADC1, ADC3. */ +#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 channel voltage always below Vdda. + On STM32L4, ADC channel available only on ADC instances: ADC1, ADC3. */ +#if defined(ADC1) && !defined(ADC2) +#define LL_ADC_CHANNEL_DAC1CH1 (LL_ADC_CHANNEL_17 | ADC_CHANNEL_ID_INTERNAL_CH | \ + ADC_CHANNEL_ID_INTERNAL_CH_2) /*!< ADC internal channel + connected to DAC1 channel 1, channel specific to ADC1. This channel is + shared with ADC internal channel connected to internal temperature sensor, + selection is done using function @ref LL_ADC_SetCommonPathInternalCh(). */ +#define LL_ADC_CHANNEL_DAC1CH2 (LL_ADC_CHANNEL_18 | ADC_CHANNEL_ID_INTERNAL_CH | \ + ADC_CHANNEL_ID_INTERNAL_CH_2) /*!< ADC internal channel + connected to DAC1 channel 2, channel specific to ADC1. This channel is + shared with ADC internal channel connected to Vbat, + selection is done using function @ref LL_ADC_SetCommonPathInternalCh(). */ +#elif defined(ADC2) +#define LL_ADC_CHANNEL_DAC1CH1_ADC2 (LL_ADC_CHANNEL_17 | ADC_CHANNEL_ID_INTERNAL_CH | \ + ADC_CHANNEL_ID_INTERNAL_CH_2) /*!< ADC internal channel + connected to DAC1 channel 1, channel specific to ADC2 */ +#define LL_ADC_CHANNEL_DAC1CH2_ADC2 (LL_ADC_CHANNEL_18 | ADC_CHANNEL_ID_INTERNAL_CH | \ + ADC_CHANNEL_ID_INTERNAL_CH_2) /*!< ADC internal channel + connected to DAC1 channel 2, channel specific to ADC2 */ +#if defined(ADC3) +#define LL_ADC_CHANNEL_DAC1CH1_ADC3 (LL_ADC_CHANNEL_14 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel + connected to DAC1 channel 1, channel specific to ADC3 */ +#define LL_ADC_CHANNEL_DAC1CH2_ADC3 (LL_ADC_CHANNEL_15 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel + connected to DAC1 channel 2, channel specific to ADC3 */ +#endif /* ADC3 */ +#endif /* ADC1 && !ADC2 */ +/** + * @} + */ + +/** @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_TRGO (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM1 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM1_TRGO2 (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM1 TRGO2. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM1_CH1 (ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: 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_CFGR_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: 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_CFGR_EXTSEL_1 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: 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_TRGO (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1 | \ + ADC_CFGR_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM2 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM2_CH2 (ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: 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_TIM3_TRGO (ADC_CFGR_EXTSEL_2 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM3 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM3_CH4 (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | \ + ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM3 channel 4 event (capture + compare: input capture or output capture). Trigger edge set to rising edge + (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM4_TRGO (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM4 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM4_CH4 (ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_0 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: 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_TIM6_TRGO (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | \ + ADC_CFGR_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM6 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM8_TRGO (ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1 | \ + ADC_CFGR_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM8 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM8_TRGO2 (ADC_CFGR_EXTSEL_3 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM8 TRGO2. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM15_TRGO (ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | \ + ADC_CFGR_EXTSEL_1 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: TIM15 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_EXTI_LINE11 (ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1 | \ + ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular + conversion trigger from external peripheral: 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_CFGR_EXTEN_0) /*!< ADC group regular conversion + trigger polarity set to rising edge */ +#define LL_ADC_REG_TRIG_EXT_FALLING (ADC_CFGR_EXTEN_1) /*!< ADC group regular conversion + trigger polarity set to falling edge */ +#define LL_ADC_REG_TRIG_EXT_RISINGFALLING (ADC_CFGR_EXTEN_1 | ADC_CFGR_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 performed in single mode: + one conversion per trigger */ +#define LL_ADC_REG_CONV_CONTINUOUS (ADC_CFGR_CONT) /*!< ADC conversions 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_CFGR_DMAEN) /*!< 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_CFGR_DMACFG | ADC_CFGR_DMAEN) /*!< 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. */ +/** + * @} + */ + +#if defined(ADC_CFGR_DFSDMCFG) &&defined(DFSDM1_Channel0) +/** @defgroup ADC_LL_EC_REG_DFSDM_TRANSFER ADC group regular - DFSDM transfer of ADC conversion data + * @{ + */ +#define LL_ADC_REG_DFSDM_TRANSFER_NONE (0x00000000UL) /*!< ADC conversions are not transferred by DFSDM. */ +#define LL_ADC_REG_DFSDM_TRANSFER_ENABLE (ADC_CFGR_DFSDMCFG) /*!< ADC conversion data are transferred to DFSDM for + post processing. The ADC conversion data format must be 16-bit signed and + right aligned, refer to reference manual. + DFSDM transfer cannot be used if DMA transfer is enabled. */ +/** + * @} + */ +#endif /* ADC_CFGR_DFSDMCFG */ + +#if defined(ADC_SMPR1_SMPPLUS) +/** @defgroup ADC_LL_EC_SAMPLINGTIME_COMMON_CONFIG ADC instance - ADC sampling time common configuration + * @{ + */ +#define LL_ADC_SAMPLINGTIME_COMMON_DEFAULT (0x00000000UL) /*!< ADC sampling time let to default settings. */ +#define LL_ADC_SAMPLINGTIME_COMMON_3C5_REPL_2C5 (ADC_SMPR1_SMPPLUS) /*!< ADC additional sampling time 3.5 ADC clock + cycles replacing 2.5 ADC clock cycles (this applies to all channels mapped + with selection sampling time 2.5 ADC clock cycles, whatever channels mapped + on ADC groups regular or injected). */ +/** + * @} + */ +#endif /* ADC_SMPR1_SMPPLUS */ + +/** @defgroup ADC_LL_EC_REG_OVR_DATA_BEHAVIOR ADC group regular - Overrun behavior on conversion data + * @{ + */ +#define LL_ADC_REG_OVR_DATA_PRESERVED (0x00000000UL) /*!< ADC group regular behavior in case of overrun: + data preserved */ +#define LL_ADC_REG_OVR_DATA_OVERWRITTEN (ADC_CFGR_OVRMOD) /*!< ADC group regular behavior in case of overrun: + data overwritten */ +/** + * @} + */ + +/** @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 sequencerenable + 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_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enable with sequence interruption every rank */ +#define LL_ADC_REG_SEQ_DISCONT_2RANKS (ADC_CFGR_DISCNUM_0 | ADC_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enabled with sequence interruption every 2 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_3RANKS (ADC_CFGR_DISCNUM_1 | ADC_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enable with sequence interruption every 3 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_4RANKS (ADC_CFGR_DISCNUM_1 | ADC_CFGR_DISCNUM_0 \ + | ADC_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enable with sequence interruption every 4 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_5RANKS (ADC_CFGR_DISCNUM_2 | ADC_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enable with sequence interruption every 5 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_6RANKS (ADC_CFGR_DISCNUM_2 | ADC_CFGR_DISCNUM_0 \ + | ADC_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enable with sequence interruption every 6 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_7RANKS (ADC_CFGR_DISCNUM_2 | ADC_CFGR_DISCNUM_1 \ + | ADC_CFGR_DISCEN) /*!< ADC group regular sequencer + discontinuous mode enable with sequence interruption every 7 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_8RANKS (ADC_CFGR_DISCNUM_2 | ADC_CFGR_DISCNUM_1 \ + | ADC_CFGR_DISCNUM_0 | ADC_CFGR_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_SQR1_REGOFFSET | ADC_REG_RANK_1_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 1 */ +#define LL_ADC_REG_RANK_2 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_2_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 2 */ +#define LL_ADC_REG_RANK_3 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_3_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 3 */ +#define LL_ADC_REG_RANK_4 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_4_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 4 */ +#define LL_ADC_REG_RANK_5 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_5_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 5 */ +#define LL_ADC_REG_RANK_6 (ADC_SQR2_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_SQR3_REGOFFSET | ADC_REG_RANK_10_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 10 */ +#define LL_ADC_REG_RANK_11 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_11_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 11 */ +#define LL_ADC_REG_RANK_12 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_12_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 12 */ +#define LL_ADC_REG_RANK_13 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_13_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 13 */ +#define LL_ADC_REG_RANK_14 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_14_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 14 */ +#define LL_ADC_REG_RANK_15 (ADC_SQR4_REGOFFSET | ADC_REG_RANK_15_SQRX_BITOFFSET_POS) /*!< ADC group + regular sequencer rank 15 */ +#define LL_ADC_REG_RANK_16 (ADC_SQR4_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_TRGO (ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM1 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM1_TRGO2 (ADC_JSQR_JEXTSEL_3 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM1 TRGO2. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM1_CH4 (ADC_JSQR_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: 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_TIM2_TRGO (ADC_JSQR_JEXTSEL_1 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM2 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM2_CH1 (ADC_JSQR_JEXTSEL_1 | ADC_JSQR_JEXTSEL_0 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: 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_TIM3_TRGO (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_2 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM3 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM3_CH1 (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_2 | \ + ADC_JSQR_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM3 channel 1 event (capture + compare: input capture or output capture). Trigger edge set to rising edge + (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM3_CH3 (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_1 | \ + ADC_JSQR_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM3 channel 3 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_JSQR_JEXTSEL_2 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: 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_TRGO (ADC_JSQR_JEXTSEL_2 | ADC_JSQR_JEXTSEL_0 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM4 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM6_TRGO (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_2 | \ + ADC_JSQR_JEXTSEL_1 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM6 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM8_CH4 (ADC_JSQR_JEXTSEL_2 | ADC_JSQR_JEXTSEL_1 | \ + ADC_JSQR_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: 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_TIM8_TRGO (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_0 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM8 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM8_TRGO2 (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_1 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM8 TRGO2. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM15_TRGO (ADC_JSQR_JEXTSEL_3 | ADC_JSQR_JEXTSEL_2 | \ + ADC_JSQR_JEXTSEL_1 | ADC_JSQR_JEXTSEL_0 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: TIM15 TRGO. Trigger edge set to + rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 (ADC_JSQR_JEXTSEL_2 | ADC_JSQR_JEXTSEL_1 | \ + ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected + conversion trigger from external peripheral: 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_JSQR_JEXTEN_0) /*!< ADC group injected conversion + trigger polarity set to rising edge */ +#define LL_ADC_INJ_TRIG_EXT_FALLING (ADC_JSQR_JEXTEN_1 ) /*!< ADC group injected conversion + trigger polarity set to falling edge */ +#define LL_ADC_INJ_TRIG_EXT_RISINGFALLING (ADC_JSQR_JEXTEN_1 | ADC_JSQR_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_CFGR_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_CONTEXT_QUEUE ADC group injected - Context queue mode + * @{ + */ +#define LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE (0x00000000UL) /* Group injected sequence context queue is enabled + and can contain up to 2 contexts. When all contexts have been processed, + the queue maintains the last context active perpetually. */ +#define LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY (ADC_CFGR_JQM) /* Group injected sequence context queue is enabled + and can contain up to 2 contexts. When all contexts have been processed, + the queue is empty and injected group triggers are disabled. */ +#define LL_ADC_INJ_QUEUE_DISABLE (ADC_CFGR_JQDIS) /* Group injected sequence context queue is disabled: + only 1 sequence can be configured and is active perpetually. */ +/** + * @} + */ + +/** @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_CFGR_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_INJ_RANK_1_JSQR_BITOFFSET_POS) /*!< ADC group inj. sequencer rank 1 */ +#define LL_ADC_INJ_RANK_2 (ADC_JDR2_REGOFFSET \ + | ADC_INJ_RANK_2_JSQR_BITOFFSET_POS) /*!< ADC group inj. sequencer rank 2 */ +#define LL_ADC_INJ_RANK_3 (ADC_JDR3_REGOFFSET \ + | ADC_INJ_RANK_3_JSQR_BITOFFSET_POS) /*!< ADC group inj. sequencer rank 3 */ +#define LL_ADC_INJ_RANK_4 (ADC_JDR4_REGOFFSET \ + | ADC_INJ_RANK_4_JSQR_BITOFFSET_POS) /*!< ADC group inj. sequencer rank 4 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_CHANNEL_SAMPLINGTIME Channel - Sampling time + * @{ + */ +#define LL_ADC_SAMPLINGTIME_2CYCLES_5 (0x00000000UL) /*!< Sampling time 2.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_6CYCLES_5 (ADC_SMPR2_SMP10_0) /*!< Sampling time 6.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_12CYCLES_5 (ADC_SMPR2_SMP10_1) /*!< Sampling time 12.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_24CYCLES_5 (ADC_SMPR2_SMP10_1 \ + | ADC_SMPR2_SMP10_0) /*!< Sampling time 24.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_47CYCLES_5 (ADC_SMPR2_SMP10_2) /*!< Sampling time 47.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_92CYCLES_5 (ADC_SMPR2_SMP10_2 \ + | ADC_SMPR2_SMP10_0) /*!< Sampling time 92.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_247CYCLES_5 (ADC_SMPR2_SMP10_2 \ + | ADC_SMPR2_SMP10_1) /*!< Sampling time 247.5 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_640CYCLES_5 (ADC_SMPR2_SMP10_2 \ + | ADC_SMPR2_SMP10_1 \ + | ADC_SMPR2_SMP10_0) /*!< Sampling time 640.5 ADC clock cycles */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_CHANNEL_SINGLE_DIFF_ENDING Channel - Single or differential ending + * @{ + */ +#define LL_ADC_SINGLE_ENDED ( ADC_CALFACT_CALFACT_S) /*!< ADC channel ending + set to single ended (literal also used to set calibration mode) */ +#define LL_ADC_DIFFERENTIAL_ENDED (ADC_CR_ADCALDIF | ADC_CALFACT_CALFACT_D) /*!< ADC channel ending + set to differential (literal also used to set calibration mode) */ +#define LL_ADC_BOTH_SINGLE_DIFF_ENDED (LL_ADC_SINGLE_ENDED | LL_ADC_DIFFERENTIAL_ENDED) /*!< ADC channel ending + set to both single ended and differential (literal used only to set + calibration factors) */ +/** + * @} + */ + +/** @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 */ +#define LL_ADC_AWD2 (ADC_AWD_CR23_CHANNEL_MASK \ + | ADC_AWD_CR2_REGOFFSET) /*!< ADC analog watchdog number 2 */ +#define LL_ADC_AWD3 (ADC_AWD_CR23_CHANNEL_MASK \ + | ADC_AWD_CR3_REGOFFSET) /*!< ADC analog watchdog number 3 */ +/** + * @} + */ + +/** @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_AWD_CR23_CHANNEL_MASK \ + | ADC_CFGR_AWD1EN) /*!< ADC analog watchdog monitoring + of all channels, converted by group regular only */ +#define LL_ADC_AWD_ALL_CHANNELS_INJ (ADC_AWD_CR23_CHANNEL_MASK \ + | ADC_CFGR_JAWD1EN) /*!< ADC analog watchdog monitoring + of all channels, converted by group injected only */ +#define LL_ADC_AWD_ALL_CHANNELS_REG_INJ (ADC_AWD_CR23_CHANNEL_MASK \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN) /*!< 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN0, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_0_INJ ((LL_ADC_CHANNEL_0 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN0, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_0_REG_INJ ((LL_ADC_CHANNEL_0 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN1, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_1_INJ ((LL_ADC_CHANNEL_1 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN1, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_1_REG_INJ ((LL_ADC_CHANNEL_1 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN2, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_2_INJ ((LL_ADC_CHANNEL_2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN2, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_2_REG_INJ ((LL_ADC_CHANNEL_2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN3, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_3_INJ ((LL_ADC_CHANNEL_3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN3, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_3_REG_INJ ((LL_ADC_CHANNEL_3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN4, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_4_INJ ((LL_ADC_CHANNEL_4 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN4, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_4_REG_INJ ((LL_ADC_CHANNEL_4 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN5, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_5_INJ ((LL_ADC_CHANNEL_5 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN5, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_5_REG_INJ ((LL_ADC_CHANNEL_5 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN6, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_6_INJ ((LL_ADC_CHANNEL_6 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN6, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_6_REG_INJ ((LL_ADC_CHANNEL_6 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN7, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_7_INJ ((LL_ADC_CHANNEL_7 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN7, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_7_REG_INJ ((LL_ADC_CHANNEL_7 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN8, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_8_INJ ((LL_ADC_CHANNEL_8 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN8, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_8_REG_INJ ((LL_ADC_CHANNEL_8 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN9, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_9_INJ ((LL_ADC_CHANNEL_9 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN9, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_9_REG_INJ ((LL_ADC_CHANNEL_9 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN10, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_10_INJ ((LL_ADC_CHANNEL_10 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN10, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_10_REG_INJ ((LL_ADC_CHANNEL_10 & ADC_CHANNEL_ID_MASK)\ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN11, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_11_INJ ((LL_ADC_CHANNEL_11 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN11, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_11_REG_INJ ((LL_ADC_CHANNEL_11 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN12, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_12_INJ ((LL_ADC_CHANNEL_12 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN12, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_12_REG_INJ ((LL_ADC_CHANNEL_12 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN13, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_13_INJ ((LL_ADC_CHANNEL_13 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN13, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_13_REG_INJ ((LL_ADC_CHANNEL_13 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN14, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_14_INJ ((LL_ADC_CHANNEL_14 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN14, converted by group only */ +#define LL_ADC_AWD_CHANNEL_14_REG_INJ ((LL_ADC_CHANNEL_14 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + monitoring of ADC channel ADCx_IN15, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_15_INJ ((LL_ADC_CHANNEL_15 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN15, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_15_REG_INJ ((LL_ADC_CHANNEL_15 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN16, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_16_INJ ((LL_ADC_CHANNEL_16 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN16, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_16_REG_INJ ((LL_ADC_CHANNEL_16 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN17, converted by group regular only */ + #define LL_ADC_AWD_CHANNEL_17_INJ ((LL_ADC_CHANNEL_17 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN17, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_17_REG_INJ ((LL_ADC_CHANNEL_17 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN18, converted by group regular only */ + #define LL_ADC_AWD_CHANNEL_18_INJ ((LL_ADC_CHANNEL_18 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel ADCx_IN18, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_18_REG_INJ ((LL_ADC_CHANNEL_18 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC channel 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_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< 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_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< 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_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< 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_TEMPSENSOR_REG ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to internal temperature sensor, + converted by group regular only */ +#define LL_ADC_AWD_CH_TEMPSENSOR_INJ ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to internal temperature sensor, + converted by group injected only */ +#define LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to internal temperature sensor, + converted by either group regular or injected */ +#define LL_ADC_AWD_CH_VBAT_REG ((LL_ADC_CHANNEL_VBAT & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to Vbat/3: Vbat + voltage through a divider ladder of factor 1/3 to have channel voltage + always below Vdda, converted by group regular only */ +#define LL_ADC_AWD_CH_VBAT_INJ ((LL_ADC_CHANNEL_VBAT & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to Vbat/3: Vbat + voltage through a divider ladder of factor 1/3 to have channel voltage + 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_CFGR_JAWD1EN | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog + of ADC internal channel connected to Vbat/3: Vbat + voltage through a divider ladder of factor 1/3 to have channel voltage + always below Vdda */ +#if defined(ADC1) && !defined(ADC2) +#define LL_ADC_AWD_CH_DAC1CH1_REG ((LL_ADC_CHANNEL_DAC1CH1 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC1, converted by group regular only */ +#define LL_ADC_AWD_CH_DAC1CH1_INJ ((LL_ADC_CHANNEL_DAC1CH1 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC1, converted by group injected only */ +#define LL_ADC_AWD_CH_DAC1CH1_REG_INJ ((LL_ADC_CHANNEL_DAC1CH1 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC1, converted by either group regular or injected */ +#define LL_ADC_AWD_CH_DAC1CH2_REG ((LL_ADC_CHANNEL_DAC1CH2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC1, converted by group regular only */ +#define LL_ADC_AWD_CH_DAC1CH2_INJ ((LL_ADC_CHANNEL_DAC1CH2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC1, converted by group injected only */ +#define LL_ADC_AWD_CH_DAC1CH2_REG_INJ ((LL_ADC_CHANNEL_DAC1CH2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC1, converted by either group regular or injected */ +#elif defined(ADC2) +#define LL_ADC_AWD_CH_DAC1CH1_ADC2_REG ((LL_ADC_CHANNEL_DAC1CH1_ADC2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC2, converted by group regular only */ +#define LL_ADC_AWD_CH_DAC1CH1_ADC2_INJ ((LL_ADC_CHANNEL_DAC1CH1_ADC2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC2, converted by group injected only */ +#define LL_ADC_AWD_CH_DAC1CH1_ADC2_REG_INJ ((LL_ADC_CHANNEL_DAC1CH1_ADC2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC2, converted by either group regular or injected */ +#define LL_ADC_AWD_CH_DAC1CH2_ADC2_REG ((LL_ADC_CHANNEL_DAC1CH2_ADC2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC2, converted by group regular only */ +#define LL_ADC_AWD_CH_DAC1CH2_ADC2_INJ ((LL_ADC_CHANNEL_DAC1CH2_ADC2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC2, converted by group injected only */ +#define LL_ADC_AWD_CH_DAC1CH2_ADC2_REG_INJ ((LL_ADC_CHANNEL_DAC1CH2_ADC2 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC2, converted by either group regular or injected */ +#if defined(ADC3) +#define LL_ADC_AWD_CH_DAC1CH1_ADC3_REG ((LL_ADC_CHANNEL_DAC1CH1_ADC3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC3, converted by group regular only */ +#define LL_ADC_AWD_CH_DAC1CH1_ADC3_INJ ((LL_ADC_CHANNEL_DAC1CH1_ADC3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC3, converted by group injected only */ +#define LL_ADC_AWD_CH_DAC1CH1_ADC3_REG_INJ ((LL_ADC_CHANNEL_DAC1CH1_ADC3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 1, + channel specific to ADC3, converted by either group regular or injected */ +#define LL_ADC_AWD_CH_DAC1CH2_ADC3_REG ((LL_ADC_CHANNEL_DAC1CH2_ADC3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC3, converted by group regular only */ +#define LL_ADC_AWD_CH_DAC1CH2_ADC3_INJ ((LL_ADC_CHANNEL_DAC1CH2_ADC3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC3, converted by group injected only */ +#define LL_ADC_AWD_CH_DAC1CH2_ADC3_REG_INJ ((LL_ADC_CHANNEL_DAC1CH2_ADC3 & ADC_CHANNEL_ID_MASK) \ + | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN \ + | ADC_CFGR_AWD1SGL) /*!< ADC analog watchdog monitoring + of ADC internal channel connected to DAC1 channel 2, + channel specific to ADC3, converted by either group regular or injected */ +#endif /* ADC3 */ +#endif /* ADC1 && !ADC2 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_AWD_THRESHOLDS Analog watchdog - Thresholds + * @{ + */ +#define LL_ADC_AWD_THRESHOLD_HIGH (ADC_TR1_HT1) /*!< ADC analog watchdog threshold high */ +#define LL_ADC_AWD_THRESHOLD_LOW (ADC_TR1_LT1) /*!< ADC analog watchdog threshold low */ +#define LL_ADC_AWD_THRESHOLDS_HIGH_LOW (ADC_TR1_HT1 \ + | ADC_TR1_LT1) /*!< ADC analog watchdog both thresholds high and low + concatenated into the same data */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_OVS_SCOPE Oversampling - Oversampling scope + * @{ + */ +#define LL_ADC_OVS_DISABLE (0x00000000UL) /*!< ADC oversampling disabled. */ +#define LL_ADC_OVS_GRP_REGULAR_CONTINUED (ADC_CFGR2_ROVSE) /*!< ADC oversampling on conversions of + ADC group regular. If group injected interrupts group regular: + when ADC group injected is triggered, the oversampling on ADC group regular + is temporary stopped and continued afterwards. */ +#define LL_ADC_OVS_GRP_REGULAR_RESUMED (ADC_CFGR2_ROVSM | ADC_CFGR2_ROVSE) /*!< ADC oversampling on conversions of + ADC group regular. If group injected interrupts group regular: + when ADC group injected is triggered, the oversampling on ADC group regular + is resumed from start (oversampler buffer reset). */ +#define LL_ADC_OVS_GRP_INJECTED (ADC_CFGR2_JOVSE) /*!< ADC oversampling on conversions of + ADC group injected. */ +#define LL_ADC_OVS_GRP_INJ_REG_RESUMED (ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSE) /*!< ADC oversampling on conversions of + both ADC groups regular and injected. If group injected interrupting group + regular: when ADC group injected is triggered, the oversampling on ADC group + regular is resumed from start (oversampler buffer reset). */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_OVS_DISCONT_MODE Oversampling - Discontinuous mode + * @{ + */ +#define LL_ADC_OVS_REG_CONT (0x00000000UL) /*!< ADC oversampling discontinuous mode: continuous mode +(all conversions of oversampling ratio are done from 1 trigger) */ +#define LL_ADC_OVS_REG_DISCONT (ADC_CFGR2_TROVS) /*!< ADC oversampling discontinuous mode: discontinuous + mode (each conversion of oversampling ratio needs a trigger) */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_OVS_RATIO Oversampling - Ratio + * @{ + */ +#define LL_ADC_OVS_RATIO_2 (0x00000000UL) /*!< ADC oversampling ratio of 2 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_4 (ADC_CFGR2_OVSR_0) /*!< ADC oversampling ratio of 4 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_8 (ADC_CFGR2_OVSR_1) /*!< ADC oversampling ratio of 8 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_16 (ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSR_0) /*!< ADC oversampling ratio of 16 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_32 (ADC_CFGR2_OVSR_2) /*!< ADC oversampling ratio of 32 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_64 (ADC_CFGR2_OVSR_2 | ADC_CFGR2_OVSR_0) /*!< ADC oversampling ratio of 64 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_128 (ADC_CFGR2_OVSR_2 | ADC_CFGR2_OVSR_1) /*!< ADC oversampling ratio of 128 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +#define LL_ADC_OVS_RATIO_256 (ADC_CFGR2_OVSR_2 | ADC_CFGR2_OVSR_1 \ + | ADC_CFGR2_OVSR_0) /*!< ADC oversampling ratio of 256 + (sum of conversions data computed to result as oversampling conversion data + (before potential shift) */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_OVS_SHIFT Oversampling - Data right shift + * @{ + */ +#define LL_ADC_OVS_SHIFT_NONE (0x00000000UL) /*!< ADC oversampling no shift + (sum of the ADC conversions data is not divided to result as oversampling + conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_1 (ADC_CFGR2_OVSS_0) /*!< ADC oversampling right shift of 1 + (sum of the ADC conversions data (after OVS ratio) is divided by 2 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_2 (ADC_CFGR2_OVSS_1) /*!< ADC oversampling right shift of 2 + (sum of the ADC conversions data (after OVS ratio) is divided by 4 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_3 (ADC_CFGR2_OVSS_1 | ADC_CFGR2_OVSS_0) /*!< ADC oversampling right shift of 3 + (sum of the ADC conversions data (after OVS ratio) is divided by 8 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_4 (ADC_CFGR2_OVSS_2) /*!< ADC oversampling right shift of 4 + (sum of the ADC conversions data (after OVS ratio) is divided by 16 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_5 (ADC_CFGR2_OVSS_2 | ADC_CFGR2_OVSS_0) /*!< ADC oversampling right shift of 5 + (sum of the ADC conversions data (after OVS ratio) is divided by 32 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_6 (ADC_CFGR2_OVSS_2 | ADC_CFGR2_OVSS_1) /*!< ADC oversampling right shift of 6 + (sum of the ADC conversions data (after OVS ratio) is divided by 64 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_7 (ADC_CFGR2_OVSS_2 | ADC_CFGR2_OVSS_1 \ + | ADC_CFGR2_OVSS_0) /*!< ADC oversampling right shift of 7 + (sum of the ADC conversions data (after OVS ratio) is divided by 128 + to result as oversampling conversion data) */ +#define LL_ADC_OVS_SHIFT_RIGHT_8 (ADC_CFGR2_OVSS_3) /*!< ADC oversampling right shift of 8 + (sum of the ADC conversions data (after OVS ratio) is divided by 256 + to result as oversampling conversion data) */ +/** + * @} + */ + +#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_DUAL_2 | ADC_CCR_DUAL_1) /*!< ADC dual mode enabled: group regular + simultaneous */ +#define LL_ADC_MULTI_DUAL_REG_INTERL (ADC_CCR_DUAL_2 | ADC_CCR_DUAL_1 \ + | ADC_CCR_DUAL_0) /*!< ADC dual mode enabled: Combined group + regular interleaved */ +#define LL_ADC_MULTI_DUAL_INJ_SIMULT (ADC_CCR_DUAL_2 | ADC_CCR_DUAL_0) /*!< ADC dual mode enabled: group injected + simultaneous */ +#define LL_ADC_MULTI_DUAL_INJ_ALTERN (ADC_CCR_DUAL_3 | ADC_CCR_DUAL_0) /*!< ADC dual mode enabled: group injected + alternate trigger. Works only with external triggers (not SW start) */ +#define LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM (ADC_CCR_DUAL_0) /*!< ADC dual mode enabled: Combined group + regular simultaneous + group injected simultaneous */ +#define LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT (ADC_CCR_DUAL_1) /*!< ADC dual mode enabled: Combined group + regular simultaneous + group injected alternate trigger */ +#define LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM (ADC_CCR_DUAL_1 | ADC_CCR_DUAL_0) /*!< ADC dual mode enabled: Combined group + regular interleaved + group injected simultaneous */ +/** + * @} + */ + +/** @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_RES12_10B (ADC_CCR_MDMA_1) /*!< ADC multimode group regular + conversions are transferred by DMA, one DMA channel for both ADC(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 for ADC resolution of 12 and 10 bits */ +#define LL_ADC_MULTI_REG_DMA_LIMIT_RES8_6B (ADC_CCR_MDMA_1 | ADC_CCR_MDMA_0) /*!< ADC multimode group regular + conversions are transferred by DMA, one DMA channel for both ADC(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 for ADC resolution of 8 and 6 bits */ +#define LL_ADC_MULTI_REG_DMA_UNLMT_RES12_10B (ADC_CCR_DMACFG | ADC_CCR_MDMA_1) /*!< ADC multimode group regular + conversions are transferred by DMA, one DMA channel for both ADC(DMA of + ADC master), 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. + Setting for ADC resolution of 12 and 10 bits */ +#define LL_ADC_MULTI_REG_DMA_UNLMT_RES8_6B (ADC_CCR_DMACFG | ADC_CCR_MDMA_1 \ + | ADC_CCR_MDMA_0) /*!< ADC multimode group regular + conversions are transferred by DMA, one DMA channel for both ADC (DMA of + ADC master), 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. + Setting for ADC resolution of 8 and 6 bits */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_MULTI_TWOSMP_DELAY Multimode - Delay between two sampling phases + * @{ + */ +#define LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE (0x00000000UL) /*!< ADC multimode delay between two + sampling phases: 1 ADC clock cycle */ +#define LL_ADC_MULTI_TWOSMP_DELAY_2CYCLES (ADC_CCR_DELAY_0) /*!< ADC multimode delay between two + sampling phases: 2 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_3CYCLES (ADC_CCR_DELAY_1) /*!< ADC multimode delay between two + sampling phases: 3 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_4CYCLES (ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two + sampling phases: 4 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES (ADC_CCR_DELAY_2) /*!< ADC multimode delay between two + sampling phases: 5 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES (ADC_CCR_DELAY_2 | 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_2 | 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_2 | 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_3) /*!< ADC multimode delay between two + sampling phases: 9 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES (ADC_CCR_DELAY_3 | 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_3 | 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_3 | ADC_CCR_DELAY_1 \ + | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two + sampling phases: 12 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_LEGACY ADC literals legacy naming + * @{ + */ +#define LL_ADC_REG_TRIG_SW_START (LL_ADC_REG_TRIG_SOFTWARE) +#define LL_ADC_REG_TRIG_EXT_TIM1_CC1 (LL_ADC_REG_TRIG_EXT_TIM1_CH1) +#define LL_ADC_REG_TRIG_EXT_TIM1_CC2 (LL_ADC_REG_TRIG_EXT_TIM1_CH2) +#define LL_ADC_REG_TRIG_EXT_TIM1_CC3 (LL_ADC_REG_TRIG_EXT_TIM1_CH3) +#define LL_ADC_REG_TRIG_EXT_TIM2_CC2 (LL_ADC_REG_TRIG_EXT_TIM2_CH2) +#define LL_ADC_REG_TRIG_EXT_TIM3_CC4 (LL_ADC_REG_TRIG_EXT_TIM3_CH4) +#define LL_ADC_REG_TRIG_EXT_TIM4_CC4 (LL_ADC_REG_TRIG_EXT_TIM4_CH4) + +#define LL_ADC_INJ_TRIG_SW_START (LL_ADC_INJ_TRIG_SOFTWARE) +#define LL_ADC_INJ_TRIG_EXT_TIM1_CC4 (LL_ADC_INJ_TRIG_EXT_TIM1_CH4) +#define LL_ADC_INJ_TRIG_EXT_TIM2_CC1 (LL_ADC_INJ_TRIG_EXT_TIM2_CH1) +#define LL_ADC_INJ_TRIG_EXT_TIM3_CC1 (LL_ADC_INJ_TRIG_EXT_TIM3_CH1) +#define LL_ADC_INJ_TRIG_EXT_TIM3_CC3 (LL_ADC_INJ_TRIG_EXT_TIM3_CH3) +#define LL_ADC_INJ_TRIG_EXT_TIM3_CC4 (LL_ADC_INJ_TRIG_EXT_TIM3_CH4) +#define LL_ADC_INJ_TRIG_EXT_TIM8_CC4 (LL_ADC_INJ_TRIG_EXT_TIM8_CH4) + +#define LL_ADC_OVS_DATA_SHIFT_NONE (LL_ADC_OVS_SHIFT_NONE) +#define LL_ADC_OVS_DATA_SHIFT_1 (LL_ADC_OVS_SHIFT_RIGHT_1) +#define LL_ADC_OVS_DATA_SHIFT_2 (LL_ADC_OVS_SHIFT_RIGHT_2) +#define LL_ADC_OVS_DATA_SHIFT_3 (LL_ADC_OVS_SHIFT_RIGHT_3) +#define LL_ADC_OVS_DATA_SHIFT_4 (LL_ADC_OVS_SHIFT_RIGHT_4) +#define LL_ADC_OVS_DATA_SHIFT_5 (LL_ADC_OVS_SHIFT_RIGHT_5) +#define LL_ADC_OVS_DATA_SHIFT_6 (LL_ADC_OVS_SHIFT_RIGHT_6) +#define LL_ADC_OVS_DATA_SHIFT_7 (LL_ADC_OVS_SHIFT_RIGHT_7) +#define LL_ADC_OVS_DATA_SHIFT_8 (LL_ADC_OVS_SHIFT_RIGHT_8) + +/** + * @} + */ + +/** @defgroup ADC_LL_EC_HELPER_MACRO Definitions of constants used by helper macro + * @{ + */ +#define LL_ADC_TEMPERATURE_CALC_ERROR ((int16_t)0x7FFF) /* Temperature calculation error using helper macro + @ref __LL_ADC_CALC_TEMPERATURE(), due to issue on + calibration parameters. This value is coded on 16 bits + (to fit on signed word or double word) and corresponds + to an inconsistent temperature value. */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_HW_DELAYS Definitions of ADC hardware constraints delays + * @note Only ADC peripheral 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 peripheral 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 calibration time: maximum delay is 112/fADC. */ +/* (refer to device datasheet, parameter "tCAL") */ +/* - ADC enable time: maximum delay is 1 conversion cycle. */ +/* (refer to device datasheet, parameter "tSTAB") */ +/* - ADC disable time: maximum delay should be a few ADC clock cycles */ +/* - ADC stop conversion time: maximum delay should be a few ADC clock */ +/* cycles */ +/* - ADC conversion time: duration depending on ADC clock and ADC */ +/* configuration. */ +/* (refer to device reference manual, section "Timing") */ + +/* Delay for ADC stabilization time (ADC voltage regulator start-up time) */ +/* Delay set to maximum value (refer to device datasheet, */ +/* parameter "tADCVREG_STUP"). */ +/* Unit: us */ +#define LL_ADC_DELAY_INTERNAL_REGUL_STAB_US ( 20UL) /*!< Delay for ADC stabilization time (ADC voltage + regulator start-up time) */ + +/* Delay for internal voltage reference stabilization time. */ +/* Delay set to maximum value (refer to device datasheet, */ +/* parameter "tstart_vrefint"). */ +/* Unit: us */ +#define LL_ADC_DELAY_VREFINT_STAB_US ( 12UL) /*!< 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 (120UL) /*!< Delay for temperature sensor stabilization time */ +#define LL_ADC_DELAY_TEMPSENSOR_BUFFER_STAB_US ( 15UL) /*!< Delay for temperature sensor buffer stabilization + time (starting from ADC enable, refer to + @ref LL_ADC_Enable()) */ + +/* Delay required between ADC end of calibration and ADC enable. */ +/* Note: On this STM32 series, a minimum number of ADC clock cycles */ +/* are required between ADC end of calibration and ADC enable. */ +/* Wait time can be computed in user application by waiting for the */ +/* equivalent number of CPU cycles, by taking into account */ +/* ratio of CPU clock versus ADC clock prescalers. */ +/* Unit: ADC clock cycles. */ +#define LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES ( 4UL) /*!< Delay required between ADC end of calibration + and ADC enable */ + +/** + * @} + */ + +/** + * @} + */ + + +/* 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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @retval Value between Min_Data=0 and Max_Data=18 + */ +#define __LL_ADC_CHANNEL_TO_DECIMAL_NB(__CHANNEL__) \ + ((((__CHANNEL__) & ADC_CHANNEL_ID_BITFIELD_MASK) == 0UL) ? \ + ( \ + ((__CHANNEL__) & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS \ + ) \ + : \ + ( \ + (uint32_t)POSITION_VAL((__CHANNEL__)) \ + ) \ + ) + +/** + * @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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to + * 4.21 Ms/s)).\n + * (1, 2, 3, 4) 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_AWD2CR_AWD2CH_0 << (__DECIMAL_NB__)) | \ + (ADC_SMPR1_REGOFFSET | (((3UL * (__DECIMAL_NB__))) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) \ + ) \ + : \ + ( \ + ((__DECIMAL_NB__) << ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) | \ + (ADC_AWD2CR_AWD2CH_0 << (__DECIMAL_NB__)) | \ + (ADC_SMPR2_REGOFFSET | (((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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances. + * @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. + */ +#if defined (ADC1) && defined (ADC2) && defined (ADC3) +#define __LL_ADC_IS_CHANNEL_INTERNAL_AVAILABLE(__ADC_INSTANCE__, __CHANNEL__) \ + (((__ADC_INSTANCE__) == ADC1) ? \ + ( \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VREFINT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_TEMPSENSOR) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VBAT) \ + ) \ + : \ + ((__ADC_INSTANCE__) == ADC2) ? \ + ( \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VREFINT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH1_ADC2) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH2_ADC2) \ + ) \ + : \ + ((__ADC_INSTANCE__) == ADC3) ? \ + ( \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VREFINT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_TEMPSENSOR) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VBAT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH1_ADC3) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH2_ADC3) \ + ) \ + : \ + (0UL) \ + ) +#elif defined (ADC1) && defined (ADC2) +#define __LL_ADC_IS_CHANNEL_INTERNAL_AVAILABLE(__ADC_INSTANCE__, __CHANNEL__) \ + (((__ADC_INSTANCE__) == ADC1) ? \ + ( \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VREFINT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_TEMPSENSOR) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VBAT) \ + ) \ + : \ + ((__ADC_INSTANCE__) == ADC2) ? \ + ( \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VREFINT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH1_ADC2) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH2_ADC2) \ + ) \ + : \ + (0UL) \ + ) +#elif defined (ADC1) +#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) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH1) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_DAC1CH2) \ + ) +#endif /* defined (ADC1) && defined (ADC2) && defined (ADC3) */ + +/** + * @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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to + * 4.21 Ms/s)).\n + * (1, 2, 3, 4) 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 (0) + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_INJ (0) + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_0_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_1_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_2_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_3_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_4_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_5_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_6_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_7_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_8_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_9_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_10_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_11_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_12_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_13_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_14_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_15_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_16_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_17_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_18_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG_INJ + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG (0)(1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_INJ (0)(1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG_INJ (1) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG (0)(4) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_INJ (0)(4) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ (4) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG (0)(4) + * @arg @ref LL_ADC_AWD_CH_VBAT_INJ (0)(4) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG_INJ (4) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_REG (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_INJ (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_REG_INJ (2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_REG (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_INJ (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_REG_INJ (2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC2_REG (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC2_INJ (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC2_REG_INJ (2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC2_REG (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC2_INJ (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC2_REG_INJ (2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC3_REG (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC3_INJ (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC3_REG_INJ (3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC3_REG (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC3_INJ (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC3_REG_INJ (3)(6) + * + * (0) On STM32L4, parameter available only on analog watchdog number: AWD1.\n + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3. + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances. + */ +#define __LL_ADC_ANALOGWD_CHANNEL_GROUP(__CHANNEL__, __GROUP__) \ + (((__GROUP__) == LL_ADC_GROUP_REGULAR) \ + ? (((__CHANNEL__) & ADC_CHANNEL_ID_MASK) | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) \ + : \ + ((__GROUP__) == LL_ADC_GROUP_INJECTED) \ + ? (((__CHANNEL__) & ADC_CHANNEL_ID_MASK) | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1SGL) \ + : \ + (((__CHANNEL__) & ADC_CHANNEL_ID_MASK) | ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) \ + ) + +/** + * @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_ConfigAnalogWDThresholds() + * or @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_CFGR_RES_BITOFFSET_POS - 1U ))) + +/** + * @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_CFGR_RES_BITOFFSET_POS - 1U ))) + +/** + * @brief Helper macro to get the ADC analog watchdog threshold high + * or low from raw value containing both thresholds concatenated. + * @note To be used with function @ref LL_ADC_GetAnalogWDThresholds(). + * Example, to get analog watchdog threshold high from the register raw value: + * __LL_ADC_ANALOGWD_THRESHOLDS_HIGH_LOW(LL_ADC_AWD_THRESHOLD_HIGH, ); + * @param __AWD_THRESHOLD_TYPE__ This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD_THRESHOLD_HIGH + * @arg @ref LL_ADC_AWD_THRESHOLD_LOW + * @param __AWD_THRESHOLDS__ Value between Min_Data=0x00000000 and Max_Data=0xFFFFFFFF + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +#define __LL_ADC_ANALOGWD_THRESHOLDS_HIGH_LOW(__AWD_THRESHOLD_TYPE__, __AWD_THRESHOLDS__) \ + (((__AWD_THRESHOLDS__) >> (((__AWD_THRESHOLD_TYPE__) & ADC_AWD_TRX_BIT_HIGH_MASK) >> ADC_AWD_TRX_BIT_HIGH_SHIFT4)) \ + & LL_ADC_AWD_THRESHOLD_LOW) + +/** + * @brief Helper macro to set the ADC calibration value with both single ended + * and differential modes calibration factors concatenated. + * @note To be used with function @ref LL_ADC_SetCalibrationFactor(). + * Example, to set calibration factors single ended to 0x55 + * and differential ended to 0x2A: + * LL_ADC_SetCalibrationFactor( + * ADC1, + * __LL_ADC_CALIB_FACTOR_SINGLE_DIFF(0x55, 0x2A)) + * @param __CALIB_FACTOR_SINGLE_ENDED__ Value between Min_Data=0x00 and Max_Data=0x7F + * @param __CALIB_FACTOR_DIFFERENTIAL__ Value between Min_Data=0x00 and Max_Data=0x7F + * @retval Value between Min_Data=0x00000000 and Max_Data=0xFFFFFFFF + */ +#define __LL_ADC_CALIB_FACTOR_SINGLE_DIFF(__CALIB_FACTOR_SINGLE_ENDED__, __CALIB_FACTOR_DIFFERENTIAL__) \ + (((__CALIB_FACTOR_DIFFERENTIAL__) << ADC_CALFACT_CALFACT_D_Pos) | (__CALIB_FACTOR_SINGLE_ENDED__)) + +#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__) >> ((ADC_CDR_RDATA_SLV_Pos) & ~(__ADC_MULTI_MASTER_SLAVE__))) & ADC_CDR_RDATA_MST) +#endif /* ADC_MULTIMODE_SUPPORT */ + +#if defined(ADC_MULTIMODE_SUPPORT) +/** + * @brief Helper macro to select, from a ADC instance, to which ADC instance + * it has a dependence in multimode (ADC master of the corresponding + * ADC common instance). + * @note In case of device with multimode available and a mix of + * ADC instances compliant and not compliant with multimode feature, + * ADC instances not compliant with multimode feature are + * considered as master instances (do not depend to + * any other ADC instance). + * @param __ADCx__ ADC instance + * @retval __ADCx__ ADC instance master of the corresponding ADC common instance + */ +#if defined(ADC2) +#define __LL_ADC_MULTI_INSTANCE_MASTER(__ADCx__) \ + ((((__ADCx__) == ADC2))? \ + (ADC1) \ + : \ + (__ADCx__) \ + ) +#else +#define __LL_ADC_MULTI_INSTANCE_MASTER(__ADCx__) \ + (__ADCx__) +#endif /* ADC2 */ +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @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 /* defined(ADC1) && defined(ADC2) && defined(ADC3) */ + +/** + * @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 /* defined(ADC1) && defined(ADC2) && defined(ADC3) */ + +/** + * @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 full-scale digital value (unit: digital value of ADC conversion data) + */ +#define __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__) \ + (0xFFFUL >> ((__ADC_RESOLUTION__) >> (ADC_CFGR_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 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_CFGR_RES_BITOFFSET_POS - 1UL))) \ + >> ((__ADC_RESOLUTION_TARGET__) >> (ADC_CFGR_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__) \ +) + +/* Legacy define */ +#define __LL_ADC_CALC_DATA_VOLTAGE() __LL_ADC_CALC_DATA_TO_VOLTAGE() + +/** + * @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) \ +) + +/** + * @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) + * In case or error, value LL_ADC_TEMPERATURE_CALC_ERROR is returned (inconsistent temperature value) + */ +#define __LL_ADC_CALC_TEMPERATURE(__VREFANALOG_VOLTAGE__,\ + __TEMPSENSOR_ADC_DATA__,\ + __ADC_RESOLUTION__)\ +((((int32_t)*TEMPSENSOR_CAL2_ADDR - (int32_t)*TEMPSENSOR_CAL1_ADDR) != 0) ? \ + (((( ((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 \ + ) \ + : \ + ((int32_t)LL_ADC_TEMPERATURE_CALC_ERROR) \ +) + +/** + * @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 12 bits + * (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 STM32L4, 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 STM32L4, refer to datasheet parameter "V30" (corresponding to TS_CAL1). + * @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+) value (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_ADC_DATA__) * (__VREFANALOG_VOLTAGE__)) \ + / __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__)) \ + * 1000UL) \ + - \ + (int32_t)(((__TEMPSENSOR_TYP_CALX_V__)) \ + * 1000UL) \ + ) \ + ) / (int32_t)(__TEMPSENSOR_TYP_AVGSLOPE__) \ + ) + (int32_t)(__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(const ADC_TypeDef *ADCx, uint32_t Register) +{ + uint32_t data_reg_addr; + + 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(const ADC_TypeDef *ADCx, uint32_t Register) +{ + /* Prevent unused argument(s) compilation warning */ + (void)(Register); + + /* Retrieve address of register DR */ + return (uint32_t) &(ADCx->DR); +} +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @} + */ + +/** @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. + * @note On this STM32 series, if ADC group injected is used, some + * clock ratio constraints between ADC clock and AHB clock + * must be respected. + * Refer to reference manual. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * All ADC instances of the ADC common group must be disabled. + * This check can be done with function @ref LL_ADC_IsEnabled() for each + * ADC instance or by using helper macro helper macro + * @ref __LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(). + * @rmtoll CCR CKMODE LL_ADC_SetCommonClock\n + * CCR PRESC 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_DIV1 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV2 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV4 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV1 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV2 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV4 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV6 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV8 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV10 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV12 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV16 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV32 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV64 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV128 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV256 + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetCommonClock(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t CommonClock) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_CKMODE | ADC_CCR_PRESC, CommonClock); +} + +/** + * @brief Get parameter common to several ADC: Clock source and prescaler. + * @rmtoll CCR CKMODE LL_ADC_GetCommonClock\n + * CCR PRESC 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_DIV1 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV2 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV4 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV1 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV2 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV4 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV6 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV8 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV10 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV12 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV16 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV32 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV64 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV128 + * @arg @ref LL_ADC_CLOCK_ASYNC_DIV256 + */ +__STATIC_INLINE uint32_t LL_ADC_GetCommonClock(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_CKMODE | ADC_CCR_PRESC)); +} + +/** + * @brief Set parameter common to several ADC: measurement path to + * internal channels (VrefInt, temperature sensor, ...). + * Configure all paths (overwrite current configuration). + * @note One or several values can be selected. + * Example: (LL_ADC_PATH_INTERNAL_VREFINT | + * LL_ADC_PATH_INTERNAL_TEMPSENSOR) + * The values not selected are removed from configuration. + * @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 literals @ref LL_ADC_DELAY_TEMPSENSOR_STAB_US, + * @ref LL_ADC_DELAY_TEMPSENSOR_BUFFER_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 VREFEN LL_ADC_SetCommonPathInternalCh\n + * CCR TSEN LL_ADC_SetCommonPathInternalCh\n + * CCR VBATEN 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_VREFEN | ADC_CCR_TSEN | ADC_CCR_VBATEN, PathInternal); +} + +/** + * @brief Set parameter common to several ADC: measurement path to + * internal channels (VrefInt, temperature sensor, ...). + * Add paths to the current configuration. + * @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 literals @ref LL_ADC_DELAY_TEMPSENSOR_STAB_US, + * @ref LL_ADC_DELAY_TEMPSENSOR_BUFFER_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 VREFEN LL_ADC_SetCommonPathInternalChAdd\n + * CCR TSEN LL_ADC_SetCommonPathInternalChAdd\n + * CCR VBATEN LL_ADC_SetCommonPathInternalChAdd + * @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_SetCommonPathInternalChAdd(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t PathInternal) +{ + SET_BIT(ADCxy_COMMON->CCR, PathInternal); +} + +/** + * @brief Set parameter common to several ADC: measurement path to + * internal channels (VrefInt, temperature sensor, ...). + * Remove paths to the current configuration. + * @note One or several values can be selected. + * Example: (LL_ADC_PATH_INTERNAL_VREFINT | + * LL_ADC_PATH_INTERNAL_TEMPSENSOR) + * @rmtoll CCR VREFEN LL_ADC_SetCommonPathInternalChRem\n + * CCR TSEN LL_ADC_SetCommonPathInternalChRem\n + * CCR VBATEN LL_ADC_SetCommonPathInternalChRem + * @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_SetCommonPathInternalChRem(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t PathInternal) +{ + CLEAR_BIT(ADCxy_COMMON->CCR, 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 VREFEN LL_ADC_GetCommonPathInternalCh\n + * CCR TSEN LL_ADC_GetCommonPathInternalCh\n + * CCR VBATEN 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(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_VREFEN | ADC_CCR_TSEN | ADC_CCR_VBATEN)); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_Instance Configuration of ADC hierarchical scope: ADC instance + * @{ + */ + +/** + * @brief Set ADC calibration factor in the mode single-ended + * or differential (for devices with differential mode available). + * @note This function is intended to set calibration parameters + * without having to perform a new calibration using + * @ref LL_ADC_StartCalibration(). + * @note For devices with differential mode available: + * Calibration of offset is specific to each of + * single-ended and differential modes + * (calibration factor must be specified for each of these + * differential modes, if used afterwards and if the application + * requires their calibration). + * @note In case of setting calibration factors of both modes single ended + * and differential (parameter LL_ADC_BOTH_SINGLE_DIFF_ENDED): + * both calibration factors must be concatenated. + * To perform this processing, use helper macro + * @ref __LL_ADC_CALIB_FACTOR_SINGLE_DIFF(). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be enabled, without calibration on going, without conversion + * on going on group regular. + * @rmtoll CALFACT CALFACT_S LL_ADC_SetCalibrationFactor\n + * CALFACT CALFACT_D LL_ADC_SetCalibrationFactor + * @param ADCx ADC instance + * @param SingleDiff This parameter can be one of the following values: + * @arg @ref LL_ADC_SINGLE_ENDED + * @arg @ref LL_ADC_DIFFERENTIAL_ENDED + * @arg @ref LL_ADC_BOTH_SINGLE_DIFF_ENDED + * @param CalibrationFactor Value between Min_Data=0x00 and Max_Data=0x7F + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetCalibrationFactor(ADC_TypeDef *ADCx, uint32_t SingleDiff, uint32_t CalibrationFactor) +{ + MODIFY_REG(ADCx->CALFACT, + SingleDiff & ADC_SINGLEDIFF_CALIB_FACTOR_MASK, + CalibrationFactor << (((SingleDiff & ADC_SINGLEDIFF_CALIB_F_BIT_D_MASK) + >> ADC_SINGLEDIFF_CALIB_F_BIT_D_SHIFT4) + & ~(SingleDiff & ADC_CALFACT_CALFACT_S))); +} + +/** + * @brief Get ADC calibration factor in the mode single-ended + * or differential (for devices with differential mode available). + * @note Calibration factors are set by hardware after performing + * a calibration run using function @ref LL_ADC_StartCalibration(). + * @note For devices with differential mode available: + * Calibration of offset is specific to each of + * single-ended and differential modes + * @rmtoll CALFACT CALFACT_S LL_ADC_GetCalibrationFactor\n + * CALFACT CALFACT_D LL_ADC_GetCalibrationFactor + * @param ADCx ADC instance + * @param SingleDiff This parameter can be one of the following values: + * @arg @ref LL_ADC_SINGLE_ENDED + * @arg @ref LL_ADC_DIFFERENTIAL_ENDED + * @retval Value between Min_Data=0x00 and Max_Data=0x7F + */ +__STATIC_INLINE uint32_t LL_ADC_GetCalibrationFactor(const ADC_TypeDef *ADCx, uint32_t SingleDiff) +{ + /* Retrieve bits with position in register depending on parameter */ + /* "SingleDiff". */ + /* Parameter used with mask "ADC_SINGLEDIFF_CALIB_FACTOR_MASK" because */ + /* containing other bits reserved for other purpose. */ + return (uint32_t)(READ_BIT(ADCx->CALFACT, + (SingleDiff & ADC_SINGLEDIFF_CALIB_FACTOR_MASK)) + >> ((SingleDiff & ADC_SINGLEDIFF_CALIB_F_BIT_D_MASK) >> + ADC_SINGLEDIFF_CALIB_F_BIT_D_SHIFT4)); +} + +/** + * @brief Set ADC resolution. + * Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR 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->CFGR, ADC_CFGR_RES, Resolution); +} + +/** + * @brief Get ADC resolution. + * Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @rmtoll CFGR 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_RES)); +} + +/** + * @brief Set ADC conversion data alignment. + * @note Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR 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->CFGR, ADC_CFGR_ALIGN, DataAlignment); +} + +/** + * @brief Get ADC conversion data alignment. + * @note Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @rmtoll CFGR ALIGN LL_ADC_GetDataAlignment + * @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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_ALIGN)); +} + +/** + * @brief Set ADC low power mode. + * @note Description of ADC low power modes: + * - ADC low power mode "auto wait": Dynamic low power mode, + * ADC conversions occurrences are limited to the minimum necessary + * in order to reduce power consumption. + * New ADC conversion starts only when the previous + * unitary conversion data (for ADC group regular) + * or previous sequence conversions data (for ADC group injected) + * has been retrieved by user software. + * In the meantime, ADC remains idle: does not performs any + * other conversion. + * This mode allows to automatically adapt the ADC conversions + * triggers to the speed of the software that reads the data. + * Moreover, this avoids risk of overrun for low frequency + * applications. + * How to use this low power mode: + * - It is not recommended to use with interruption or DMA + * since these modes have to clear immediately the EOC flag + * (by CPU to free the IRQ pending event or by DMA). + * Auto wait will work but fort a very short time, discarding + * its intended benefit (except specific case of high load of CPU + * or DMA transfers which can justify usage of auto wait). + * - Do use with polling: 1. Start conversion, + * 2. Later on, when conversion data is needed: poll for end of + * conversion to ensure that conversion is completed and + * retrieve ADC conversion data. This will trig another + * ADC conversion start. + * @note With ADC low power mode "auto wait", the ADC conversion data read + * is corresponding to previous ADC conversion start, independently + * of delay during which ADC was idle. + * Therefore, the ADC conversion data may be outdated: does not + * correspond to the current voltage level on the selected + * ADC channel. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR AUTDLY LL_ADC_SetLowPowerMode + * @param ADCx ADC instance + * @param LowPowerMode This parameter can be one of the following values: + * @arg @ref LL_ADC_LP_MODE_NONE + * @arg @ref LL_ADC_LP_AUTOWAIT + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetLowPowerMode(ADC_TypeDef *ADCx, uint32_t LowPowerMode) +{ + MODIFY_REG(ADCx->CFGR, ADC_CFGR_AUTDLY, LowPowerMode); +} + +/** + * @brief Get ADC low power mode: + * @note Description of ADC low power modes: + * - ADC low power mode "auto wait": Dynamic low power mode, + * ADC conversions occurrences are limited to the minimum necessary + * in order to reduce power consumption. + * New ADC conversion starts only when the previous + * unitary conversion data (for ADC group regular) + * or previous sequence conversions data (for ADC group injected) + * has been retrieved by user software. + * In the meantime, ADC remains idle: does not performs any + * other conversion. + * This mode allows to automatically adapt the ADC conversions + * triggers to the speed of the software that reads the data. + * Moreover, this avoids risk of overrun for low frequency + * applications. + * How to use this low power mode: + * - It is not recommended to use with interruption or DMA + * since these modes have to clear immediately the EOC flag + * (by CPU to free the IRQ pending event or by DMA). + * Auto wait will work but fort a very short time, discarding + * its intended benefit (except specific case of high load of CPU + * or DMA transfers which can justify usage of auto wait). + * - Do use with polling: 1. Start conversion, + * 2. Later on, when conversion data is needed: poll for end of + * conversion to ensure that conversion is completed and + * retrieve ADC conversion data. This will trig another + * ADC conversion start. + * @note With ADC low power mode "auto wait", the ADC conversion data read + * is corresponding to previous ADC conversion start, independently + * of delay during which ADC was idle. + * Therefore, the ADC conversion data may be outdated: does not + * correspond to the current voltage level on the selected + * ADC channel. + * @rmtoll CFGR AUTDLY LL_ADC_GetLowPowerMode + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_LP_MODE_NONE + * @arg @ref LL_ADC_LP_AUTOWAIT + */ +__STATIC_INLINE uint32_t LL_ADC_GetLowPowerMode(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_AUTDLY)); +} + +/** + * @brief Set ADC selected offset instance 1, 2, 3 or 4. + * @note This function set the 2 items of offset configuration: + * - ADC channel to which the offset programmed will be applied + * (independently of channel mapped on ADC group regular + * or group injected) + * - Offset level (offset to be subtracted from the raw + * converted data). + * @note 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 This function enables the offset, by default. It can be forced + * to disable state using function LL_ADC_SetOffsetState(). + * @note If a channel is mapped on several offsets numbers, only the offset + * with the lowest value is considered for the subtraction. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @note On STM32L4, some fast channels are available: fast analog inputs + * coming from GPIO pads (ADC_IN1..5). + * @rmtoll OFR1 OFFSET1_CH LL_ADC_SetOffset\n + * OFR1 OFFSET1 LL_ADC_SetOffset\n + * OFR1 OFFSET1_EN LL_ADC_SetOffset\n + * OFR2 OFFSET2_CH LL_ADC_SetOffset\n + * OFR2 OFFSET2 LL_ADC_SetOffset\n + * OFR2 OFFSET2_EN LL_ADC_SetOffset\n + * OFR3 OFFSET3_CH LL_ADC_SetOffset\n + * OFR3 OFFSET3 LL_ADC_SetOffset\n + * OFR3 OFFSET3_EN LL_ADC_SetOffset\n + * OFR4 OFFSET4_CH LL_ADC_SetOffset\n + * OFR4 OFFSET4 LL_ADC_SetOffset\n + * OFR4 OFFSET4_EN LL_ADC_SetOffset + * @param ADCx ADC instance + * @param Offsety This parameter can be one of the following values: + * @arg @ref LL_ADC_OFFSET_1 + * @arg @ref LL_ADC_OFFSET_2 + * @arg @ref LL_ADC_OFFSET_3 + * @arg @ref LL_ADC_OFFSET_4 + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @param OffsetLevel Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetOffset(ADC_TypeDef *ADCx, uint32_t Offsety, uint32_t Channel, uint32_t OffsetLevel) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->OFR1, Offsety); + + MODIFY_REG(*preg, + ADC_OFR1_OFFSET1_EN | ADC_OFR1_OFFSET1_CH | ADC_OFR1_OFFSET1, + ADC_OFR1_OFFSET1_EN | (Channel & ADC_CHANNEL_ID_NUMBER_MASK) | OffsetLevel); +} + +/** + * @brief Get for the ADC selected offset instance 1, 2, 3 or 4: + * Channel to which the offset programmed will be applied + * (independently of channel mapped on ADC group regular + * or group injected) + * @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(). + * @note On STM32L4, some fast channels are available: fast analog inputs + * coming from GPIO pads (ADC_IN1..5). + * @rmtoll OFR1 OFFSET1_CH LL_ADC_GetOffsetChannel\n + * OFR2 OFFSET2_CH LL_ADC_GetOffsetChannel\n + * OFR3 OFFSET3_CH LL_ADC_GetOffsetChannel\n + * OFR4 OFFSET4_CH LL_ADC_GetOffsetChannel + * @param ADCx ADC instance + * @param Offsety This parameter can be one of the following values: + * @arg @ref LL_ADC_OFFSET_1 + * @arg @ref LL_ADC_OFFSET_2 + * @arg @ref LL_ADC_OFFSET_3 + * @arg @ref LL_ADC_OFFSET_4 + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to + * 4.21 Ms/s)).\n + * (1, 2, 3, 4) 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_GetOffsetChannel(const ADC_TypeDef *ADCx, uint32_t Offsety) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->OFR1, Offsety); + + return (uint32_t) READ_BIT(*preg, ADC_OFR1_OFFSET1_CH); +} + +/** + * @brief Get for the ADC selected offset instance 1, 2, 3 or 4: + * Offset level (offset to be subtracted from the raw + * converted data). + * @note 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 OFR1 OFFSET1 LL_ADC_GetOffsetLevel\n + * OFR2 OFFSET2 LL_ADC_GetOffsetLevel\n + * OFR3 OFFSET3 LL_ADC_GetOffsetLevel\n + * OFR4 OFFSET4 LL_ADC_GetOffsetLevel + * @param ADCx ADC instance + * @param Offsety This parameter can be one of the following values: + * @arg @ref LL_ADC_OFFSET_1 + * @arg @ref LL_ADC_OFFSET_2 + * @arg @ref LL_ADC_OFFSET_3 + * @arg @ref LL_ADC_OFFSET_4 + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_ADC_GetOffsetLevel(const ADC_TypeDef *ADCx, uint32_t Offsety) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->OFR1, Offsety); + + return (uint32_t) READ_BIT(*preg, ADC_OFR1_OFFSET1); +} + +/** + * @brief Set for the ADC selected offset instance 1, 2, 3 or 4: + * force offset state disable or enable + * without modifying offset channel or offset value. + * @note This function should be needed only in case of offset to be + * enabled-disabled dynamically, and should not be needed in other cases: + * function LL_ADC_SetOffset() automatically enables the offset. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll OFR1 OFFSET1_EN LL_ADC_SetOffsetState\n + * OFR2 OFFSET2_EN LL_ADC_SetOffsetState\n + * OFR3 OFFSET3_EN LL_ADC_SetOffsetState\n + * OFR4 OFFSET4_EN LL_ADC_SetOffsetState + * @param ADCx ADC instance + * @param Offsety This parameter can be one of the following values: + * @arg @ref LL_ADC_OFFSET_1 + * @arg @ref LL_ADC_OFFSET_2 + * @arg @ref LL_ADC_OFFSET_3 + * @arg @ref LL_ADC_OFFSET_4 + * @param OffsetState This parameter can be one of the following values: + * @arg @ref LL_ADC_OFFSET_DISABLE + * @arg @ref LL_ADC_OFFSET_ENABLE + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetOffsetState(ADC_TypeDef *ADCx, uint32_t Offsety, uint32_t OffsetState) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->OFR1, Offsety); + + MODIFY_REG(*preg, + ADC_OFR1_OFFSET1_EN, + OffsetState); +} + +/** + * @brief Get for the ADC selected offset instance 1, 2, 3 or 4: + * offset state disabled or enabled. + * @rmtoll OFR1 OFFSET1_EN LL_ADC_GetOffsetState\n + * OFR2 OFFSET2_EN LL_ADC_GetOffsetState\n + * OFR3 OFFSET3_EN LL_ADC_GetOffsetState\n + * OFR4 OFFSET4_EN LL_ADC_GetOffsetState + * @param ADCx ADC instance + * @param Offsety This parameter can be one of the following values: + * @arg @ref LL_ADC_OFFSET_1 + * @arg @ref LL_ADC_OFFSET_2 + * @arg @ref LL_ADC_OFFSET_3 + * @arg @ref LL_ADC_OFFSET_4 + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_OFFSET_DISABLE + * @arg @ref LL_ADC_OFFSET_ENABLE + */ +__STATIC_INLINE uint32_t LL_ADC_GetOffsetState(const ADC_TypeDef *ADCx, uint32_t Offsety) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->OFR1, Offsety); + + return (uint32_t) READ_BIT(*preg, ADC_OFR1_OFFSET1_EN); +} + +#if defined(ADC_SMPR1_SMPPLUS) +/** + * @brief Set ADC sampling time common configuration impacting + * settings of sampling time channel wise. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll SMPR1 SMPPLUS LL_ADC_SetSamplingTimeCommonConfig + * @param ADCx ADC instance + * @param SamplingTimeCommonConfig This parameter can be one of the following values: + * @arg @ref LL_ADC_SAMPLINGTIME_COMMON_DEFAULT + * @arg @ref LL_ADC_SAMPLINGTIME_COMMON_3C5_REPL_2C5 + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetSamplingTimeCommonConfig(ADC_TypeDef *ADCx, uint32_t SamplingTimeCommonConfig) +{ + MODIFY_REG(ADCx->SMPR1, ADC_SMPR1_SMPPLUS, SamplingTimeCommonConfig); +} + +/** + * @brief Get ADC sampling time common configuration impacting + * settings of sampling time channel wise. + * @rmtoll SMPR1 SMPPLUS LL_ADC_GetSamplingTimeCommonConfig + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_SAMPLINGTIME_COMMON_DEFAULT + * @arg @ref LL_ADC_SAMPLINGTIME_COMMON_3C5_REPL_2C5 + */ +__STATIC_INLINE uint32_t LL_ADC_GetSamplingTimeCommonConfig(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->SMPR1, ADC_SMPR1_SMPPLUS)); +} +#endif /* ADC_SMPR1_SMPPLUS */ + +/** + * @} + */ + +/** @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 peripheral (timer event, + * external interrupt line). + * @note On this STM32 series, setting trigger source to external trigger + * also set trigger polarity to rising edge + * (default setting for compatibility with some ADC on other + * STM32 series having this setting set by HW default value). + * In case of need to modify trigger edge, use + * function @ref LL_ADC_REG_SetTriggerEdge(). + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @rmtoll CFGR EXTSEL LL_ADC_REG_SetTriggerSource\n + * CFGR 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_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_TRGO2 + * @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_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM4_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_TRGO2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM15_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) +{ + MODIFY_REG(ADCx->CFGR, ADC_CFGR_EXTEN | ADC_CFGR_EXTSEL, TriggerSource); +} + +/** + * @brief Get ADC group regular conversion trigger source: + * internal (SW start) or from external peripheral (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 CFGR EXTSEL LL_ADC_REG_GetTriggerSource\n + * CFGR 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_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_TRGO2 + * @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_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM4_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_TRGO2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM15_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_EXTI_LINE11 + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetTriggerSource(const ADC_TypeDef *ADCx) +{ + __IO uint32_t trigger_source = READ_BIT(ADCx->CFGR, ADC_CFGR_EXTSEL | ADC_CFGR_EXTEN); + + /* Value for shift of {0; 4; 8; 12} depending on value of bitfield */ + /* corresponding to ADC_CFGR_EXTEN {0; 1; 2; 3}. */ + uint32_t shift_exten = ((trigger_source & ADC_CFGR_EXTEN) >> (ADC_REG_TRIG_EXTEN_BITOFFSET_POS - 2UL)); + + /* Set bitfield corresponding to ADC_CFGR_EXTEN and ADC_CFGR_EXTSEL */ + /* to match with triggers literals definition. */ + return ((trigger_source + & (ADC_REG_TRIG_SOURCE_MASK >> shift_exten) & ADC_CFGR_EXTSEL) + | ((ADC_REG_TRIG_EDGE_MASK >> shift_exten) & ADC_CFGR_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 CFGR 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(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CFGR, ADC_CFGR_EXTEN) == (LL_ADC_REG_TRIG_SOFTWARE & ADC_CFGR_EXTEN)) ? 1UL : 0UL); +} + +/** + * @brief Set ADC group regular conversion trigger polarity. + * @note Applicable only for trigger source set to external trigger. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @rmtoll CFGR EXTEN LL_ADC_REG_SetTriggerEdge + * @param ADCx ADC instance + * @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 + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetTriggerEdge(ADC_TypeDef *ADCx, uint32_t ExternalTriggerEdge) +{ + MODIFY_REG(ADCx->CFGR, ADC_CFGR_EXTEN, ExternalTriggerEdge); +} + +/** + * @brief Get ADC group regular conversion trigger polarity. + * @note Applicable only for trigger source set to external trigger. + * @rmtoll CFGR 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_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 Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @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 Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @rmtoll SQR1 L LL_ADC_REG_GetSequencerLength + * @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(const 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. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @rmtoll CFGR DISCEN LL_ADC_REG_SetSequencerDiscont\n + * CFGR 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->CFGR, ADC_CFGR_DISCEN | ADC_CFGR_DISCNUM, SeqDiscont); +} + +/** + * @brief Get ADC group regular sequencer discontinuous mode: + * sequence subdivided and scan conversions interrupted every selected + * number of ranks. + * @rmtoll CFGR DISCEN LL_ADC_REG_GetSequencerDiscont\n + * CFGR 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_DISCEN | ADC_CFGR_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(). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @rmtoll SQR1 SQ1 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ2 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ3 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ4 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ5 LL_ADC_REG_SetSequencerRanks\n + * SQR2 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 + * SQR3 SQ10 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ11 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ12 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ13 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ14 LL_ADC_REG_SetSequencerRanks\n + * SQR4 SQ15 LL_ADC_REG_SetSequencerRanks\n + * SQR4 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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @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, + ((Rank & ADC_REG_SQRX_REGOFFSET_MASK) >> ADC_SQRX_REGOFFSET_POS)); + + MODIFY_REG(*preg, + ADC_CHANNEL_ID_NUMBER_MASK_POSBIT0 << (Rank & ADC_REG_RANK_ID_SQRX_MASK), + ((Channel & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (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 SQR1 SQ1 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ2 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ3 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ4 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ5 LL_ADC_REG_GetSequencerRanks\n + * SQR2 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 + * SQR3 SQ10 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ11 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ12 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ13 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ14 LL_ADC_REG_GetSequencerRanks\n + * SQR4 SQ15 LL_ADC_REG_GetSequencerRanks\n + * SQR4 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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to + * 4.21 Ms/s)).\n + * (1, 2, 3, 4) 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->SQR1, + ((Rank & ADC_REG_SQRX_REGOFFSET_MASK) >> ADC_SQRX_REGOFFSET_POS)); + + return (uint32_t)((READ_BIT(*preg, + ADC_CHANNEL_ID_NUMBER_MASK_POSBIT0 << (Rank & ADC_REG_RANK_ID_SQRX_MASK)) + >> (Rank & ADC_REG_RANK_ID_SQRX_MASK)) << ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS + ); +} + +/** + * @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. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @rmtoll CFGR 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->CFGR, ADC_CFGR_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 CFGR 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_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(). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR DMAEN LL_ADC_REG_SetDMATransfer\n + * CFGR DMACFG 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->CFGR, ADC_CFGR_DMAEN | ADC_CFGR_DMACFG, 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 CFGR DMAEN LL_ADC_REG_GetDMATransfer\n + * CFGR DMACFG 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_DMAEN | ADC_CFGR_DMACFG)); +} + +#if defined(ADC_CFGR_DFSDMCFG) &&defined(DFSDM1_Channel0) +/** + * @brief Set ADC group regular conversion data transfer to DFSDM. + * @note DFSDM transfer cannot be used if DMA transfer is enabled. + * @note To configure DFSDM source address (peripheral address), + * use the same function as for DMA transfer: + * function @ref LL_ADC_DMA_GetRegAddr(). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR DFSDMCFG LL_ADC_REG_GetDFSDMTransfer + * @param ADCx ADC instance + * @param DFSDMTransfer This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_DFSDM_TRANSFER_NONE + * @arg @ref LL_ADC_REG_DFSDM_TRANSFER_ENABLE + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetDFSDMTransfer(ADC_TypeDef *ADCx, uint32_t DFSDMTransfer) +{ + MODIFY_REG(ADCx->CFGR, ADC_CFGR_DFSDMCFG, DFSDMTransfer); +} + +/** + * @brief Get ADC group regular conversion data transfer to DFSDM. + * @rmtoll CFGR DFSDMCFG LL_ADC_REG_GetDFSDMTransfer + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_DFSDM_TRANSFER_NONE + * @arg @ref LL_ADC_REG_DFSDM_TRANSFER_ENABLE + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetDFSDMTransfer(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_DFSDMCFG)); +} +#endif /* ADC_CFGR_DFSDMCFG */ + +/** + * @brief Set ADC group regular behavior in case of overrun: + * data preserved or overwritten. + * @note Compatibility with devices without feature overrun: + * other devices without this feature have a behavior + * equivalent to data overwritten. + * The default setting of overrun is data preserved. + * Therefore, for compatibility with all devices, parameter + * overrun should be set to data overwritten. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @rmtoll CFGR OVRMOD LL_ADC_REG_SetOverrun + * @param ADCx ADC instance + * @param Overrun This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_OVR_DATA_PRESERVED + * @arg @ref LL_ADC_REG_OVR_DATA_OVERWRITTEN + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetOverrun(ADC_TypeDef *ADCx, uint32_t Overrun) +{ + MODIFY_REG(ADCx->CFGR, ADC_CFGR_OVRMOD, Overrun); +} + +/** + * @brief Get ADC group regular behavior in case of overrun: + * data preserved or overwritten. + * @rmtoll CFGR OVRMOD LL_ADC_REG_GetOverrun + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_OVR_DATA_PRESERVED + * @arg @ref LL_ADC_REG_OVR_DATA_OVERWRITTEN + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetOverrun(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_OVRMOD)); +} + +/** + * @} + */ + +/** @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 peripheral (timer event, + * external interrupt line). + * @note On this STM32 series, setting trigger source to external trigger + * also set trigger polarity to rising edge + * (default setting for compatibility with some ADC on other + * STM32 series having this setting set by HW default value). + * In case of need to modify trigger edge, use + * function @ref LL_ADC_INJ_SetTriggerEdge(). + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must not be disabled. Can be enabled with or without conversion + * on going on either groups regular or injected. + * @rmtoll JSQR JEXTSEL LL_ADC_INJ_SetTriggerSource\n + * JSQR 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_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_TRGO2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_TRGO2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM15_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetTriggerSource(ADC_TypeDef *ADCx, uint32_t TriggerSource) +{ + MODIFY_REG(ADCx->JSQR, ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN, TriggerSource); +} + +/** + * @brief Get ADC group injected conversion trigger source: + * internal (SW start) or from external peripheral (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 JSQR JEXTSEL LL_ADC_INJ_GetTriggerSource\n + * JSQR 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_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_TRGO2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_TRGO2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM15_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetTriggerSource(const ADC_TypeDef *ADCx) +{ + __IO uint32_t trigger_source = READ_BIT(ADCx->JSQR, ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN); + + /* Value for shift of {0; 4; 8; 12} depending on value of bitfield */ + /* corresponding to ADC_JSQR_JEXTEN {0; 1; 2; 3}. */ + uint32_t shift_jexten = ((trigger_source & ADC_JSQR_JEXTEN) >> (ADC_INJ_TRIG_EXTEN_BITOFFSET_POS - 2UL)); + + /* Set bitfield corresponding to ADC_JSQR_JEXTEN and ADC_JSQR_JEXTSEL */ + /* to match with triggers literals definition. */ + return ((trigger_source + & (ADC_INJ_TRIG_SOURCE_MASK >> shift_jexten) & ADC_JSQR_JEXTSEL) + | ((ADC_INJ_TRIG_EDGE_MASK >> shift_jexten) & ADC_JSQR_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 JSQR 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(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->JSQR, ADC_JSQR_JEXTEN) == (LL_ADC_INJ_TRIG_SOFTWARE & ADC_JSQR_JEXTEN)) ? 1UL : 0UL); +} + +/** + * @brief Set ADC group injected conversion trigger polarity. + * Applicable only for trigger source set to external trigger. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must not be disabled. Can be enabled with or without conversion + * on going on either groups regular or injected. + * @rmtoll JSQR JEXTEN LL_ADC_INJ_SetTriggerEdge + * @param ADCx ADC instance + * @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 + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetTriggerEdge(ADC_TypeDef *ADCx, uint32_t ExternalTriggerEdge) +{ + MODIFY_REG(ADCx->JSQR, ADC_JSQR_JEXTEN, ExternalTriggerEdge); +} + +/** + * @brief Get ADC group injected conversion trigger polarity. + * Applicable only for trigger source set to external trigger. + * @rmtoll JSQR 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->JSQR, ADC_JSQR_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 Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must not be disabled. Can be enabled with or without conversion + * on going on either groups regular or injected. + * @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 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(const 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 CFGR JDISCEN 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->CFGR, ADC_CFGR_JDISCEN, SeqDiscont); +} + +/** + * @brief Get ADC group injected sequencer discontinuous mode: + * sequence subdivided and scan conversions interrupted every selected + * number of ranks. + * @rmtoll CFGR JDISCEN LL_ADC_INJ_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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_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(). + * @note On STM32L4, some fast channels are available: fast analog inputs + * coming from GPIO pads (ADC_IN1..5). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must not be disabled. Can be enabled with or without conversion + * on going on either groups regular or injected. + * @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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @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. */ + MODIFY_REG(ADCx->JSQR, + (ADC_CHANNEL_ID_NUMBER_MASK >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (Rank & ADC_INJ_RANK_ID_JSQR_MASK), + ((Channel & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (Rank & ADC_INJ_RANK_ID_JSQR_MASK)); +} + +/** + * @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_GetSequencerRanks\n + * JSQR JSQ2 LL_ADC_INJ_GetSequencerRanks\n + * JSQR JSQ3 LL_ADC_INJ_GetSequencerRanks\n + * JSQR JSQ4 LL_ADC_INJ_GetSequencerRanks + * @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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to + * 4.21 Ms/s)).\n + * (1, 2, 3, 4) 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + return (uint32_t)((READ_BIT(ADCx->JSQR, + (ADC_CHANNEL_ID_NUMBER_MASK >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (Rank & ADC_INJ_RANK_ID_JSQR_MASK)) + >> (Rank & ADC_INJ_RANK_ID_JSQR_MASK)) << ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS + ); +} + +/** + * @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. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR 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->CFGR, ADC_CFGR_JAUTO, TrigAuto); +} + +/** + * @brief Get ADC group injected conversion trigger: + * independent or from ADC group regular. + * @rmtoll CFGR 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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_JAUTO)); +} + +/** + * @brief Set ADC group injected contexts queue mode. + * @note A context is a setting of group injected sequencer: + * - group injected trigger + * - sequencer length + * - sequencer ranks + * If contexts queue is disabled: + * - only 1 sequence can be configured + * and is active perpetually. + * If contexts queue is enabled: + * - up to 2 contexts can be queued + * and are checked in and out as a FIFO stack (first-in, first-out). + * - If a new context is set when queues is full, error is triggered + * by interruption "Injected Queue Overflow". + * - Two behaviors are possible when all contexts have been processed: + * the contexts queue can maintain the last context active perpetually + * or can be empty and injected group triggers are disabled. + * - Triggers can be only external (not internal SW start) + * - Caution: The sequence must be fully configured in one time + * (one write of register JSQR makes a check-in of a new context + * into the queue). + * Therefore functions to set separately injected trigger and + * sequencer channels cannot be used, register JSQR must be set + * using function @ref LL_ADC_INJ_ConfigQueueContext(). + * @note This parameter can be modified only when no conversion is on going + * on either groups regular or injected. + * @note A modification of the context mode (bit JQDIS) causes the contexts + * queue to be flushed and the register JSQR is cleared. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR JQM LL_ADC_INJ_SetQueueMode\n + * CFGR JQDIS LL_ADC_INJ_SetQueueMode + * @param ADCx ADC instance + * @param QueueMode This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_QUEUE_DISABLE + * @arg @ref LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE + * @arg @ref LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetQueueMode(ADC_TypeDef *ADCx, uint32_t QueueMode) +{ + MODIFY_REG(ADCx->CFGR, ADC_CFGR_JQM | ADC_CFGR_JQDIS, QueueMode); +} + +/** + * @brief Get ADC group injected context queue mode. + * @rmtoll CFGR JQM LL_ADC_INJ_GetQueueMode\n + * CFGR JQDIS LL_ADC_INJ_GetQueueMode + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_INJ_QUEUE_DISABLE + * @arg @ref LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE + * @arg @ref LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetQueueMode(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR, ADC_CFGR_JQM | ADC_CFGR_JQDIS)); +} + +/** + * @brief Set one context on ADC group injected that will be checked in + * contexts queue. + * @note A context is a setting of group injected sequencer: + * - group injected trigger + * - sequencer length + * - sequencer ranks + * This function is intended to be used when contexts queue is enabled, + * because the sequence must be fully configured in one time + * (functions to set separately injected trigger and sequencer channels + * cannot be used): + * Refer to function @ref LL_ADC_INJ_SetQueueMode(). + * @note In the contexts queue, only the active context can be read. + * The parameters of this function can be read using functions: + * @arg @ref LL_ADC_INJ_GetTriggerSource() + * @arg @ref LL_ADC_INJ_GetTriggerEdge() + * @arg @ref LL_ADC_INJ_GetSequencerRanks() + * @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(). + * @note On STM32L4, some fast channels are available: fast analog inputs + * coming from GPIO pads (ADC_IN1..5). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must not be disabled. Can be enabled with or without conversion + * on going on either groups regular or injected. + * @rmtoll JSQR JEXTSEL LL_ADC_INJ_ConfigQueueContext\n + * JSQR JEXTEN LL_ADC_INJ_ConfigQueueContext\n + * JSQR JL LL_ADC_INJ_ConfigQueueContext\n + * JSQR JSQ1 LL_ADC_INJ_ConfigQueueContext\n + * JSQR JSQ2 LL_ADC_INJ_ConfigQueueContext\n + * JSQR JSQ3 LL_ADC_INJ_ConfigQueueContext\n + * JSQR JSQ4 LL_ADC_INJ_ConfigQueueContext + * @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_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_TRGO2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_TRGO2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM15_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 + * @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 + * + * Note: This parameter is discarded in case of SW start: + * parameter "TriggerSource" set to "LL_ADC_INJ_TRIG_SOFTWARE". + * @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 + * @param Rank1_Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @param Rank2_Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @param Rank3_Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @param Rank4_Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_ConfigQueueContext(ADC_TypeDef *ADCx, + uint32_t TriggerSource, + uint32_t ExternalTriggerEdge, + uint32_t SequencerNbRanks, + uint32_t Rank1_Channel, + uint32_t Rank2_Channel, + uint32_t Rank3_Channel, + uint32_t Rank4_Channel) +{ + /* Set bits with content of parameter "Rankx_Channel" with bits position */ + /* in register depending on literal "LL_ADC_INJ_RANK_x". */ + /* Parameters "Rankx_Channel" and "LL_ADC_INJ_RANK_x" are used with masks */ + /* because containing other bits reserved for other purpose. */ + /* If parameter "TriggerSource" is set to SW start, then parameter */ + /* "ExternalTriggerEdge" is discarded. */ + uint32_t is_trigger_not_sw = (uint32_t)((TriggerSource != LL_ADC_INJ_TRIG_SOFTWARE) ? 1UL : 0UL); + MODIFY_REG(ADCx->JSQR, + ADC_JSQR_JEXTSEL | + ADC_JSQR_JEXTEN | + ADC_JSQR_JSQ4 | + ADC_JSQR_JSQ3 | + ADC_JSQR_JSQ2 | + ADC_JSQR_JSQ1 | + ADC_JSQR_JL, + (TriggerSource & ADC_JSQR_JEXTSEL) | + (ExternalTriggerEdge * (is_trigger_not_sw)) | + (((Rank4_Channel & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (LL_ADC_INJ_RANK_4 & ADC_INJ_RANK_ID_JSQR_MASK)) | + (((Rank3_Channel & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (LL_ADC_INJ_RANK_3 & ADC_INJ_RANK_ID_JSQR_MASK)) | + (((Rank2_Channel & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (LL_ADC_INJ_RANK_2 & ADC_INJ_RANK_ID_JSQR_MASK)) | + (((Rank1_Channel & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + << (LL_ADC_INJ_RANK_1 & ADC_INJ_RANK_ID_JSQR_MASK)) | + SequencerNbRanks + ); +} + +/** + * @} + */ + +/** @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. + * On this STM32 series, ADC processing time is: + * - 12.5 ADC clock cycles at ADC resolution 12 bits + * - 10.5 ADC clock cycles at ADC resolution 10 bits + * - 8.5 ADC clock cycles at ADC resolution 8 bits + * - 6.5 ADC clock cycles at ADC resolution 6 bits + * @note In case of ADC conversion of internal channel (VrefInt, + * temperature sensor, ...), a sampling time minimum value + * is required. + * Refer to device datasheet. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll SMPR1 SMP0 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP1 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP2 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP3 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP4 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP5 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP6 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP7 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP8 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP9 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP10 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP11 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP12 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP13 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP14 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP15 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP16 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP17 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP18 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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @param SamplingTime This parameter can be one of the following values: + * @arg @ref LL_ADC_SAMPLINGTIME_2CYCLES_5 (1) + * @arg @ref LL_ADC_SAMPLINGTIME_6CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_12CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_24CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_47CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_92CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_247CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_640CYCLES_5 + * + * (1) On some devices, ADC sampling time 2.5 ADC clock cycles + * can be replaced by 3.5 ADC clock cycles. + * Refer to function @ref LL_ADC_SetSamplingTimeCommonConfig(). + * @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, + ((Channel & ADC_CHANNEL_SMPRX_REGOFFSET_MASK) >> ADC_SMPRX_REGOFFSET_POS)); + + MODIFY_REG(*preg, + ADC_SMPR1_SMP0 << ((Channel & ADC_CHANNEL_SMPx_BITOFFSET_MASK) >> ADC_CHANNEL_SMPx_BITOFFSET_POS), + SamplingTime << ((Channel & ADC_CHANNEL_SMPx_BITOFFSET_MASK) >> ADC_CHANNEL_SMPx_BITOFFSET_POS)); +} + +/** + * @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. + * On this STM32 series, ADC processing time is: + * - 12.5 ADC clock cycles at ADC resolution 12 bits + * - 10.5 ADC clock cycles at ADC resolution 10 bits + * - 8.5 ADC clock cycles at ADC resolution 8 bits + * - 6.5 ADC clock cycles at ADC resolution 6 bits + * @rmtoll SMPR1 SMP0 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP1 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP2 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP3 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP4 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP5 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP6 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP7 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP8 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP9 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP10 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP11 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP12 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP13 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP14 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP15 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP16 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP17 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP18 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 (7) + * @arg @ref LL_ADC_CHANNEL_2 (7) + * @arg @ref LL_ADC_CHANNEL_3 (7) + * @arg @ref LL_ADC_CHANNEL_4 (7) + * @arg @ref LL_ADC_CHANNEL_5 (7) + * @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 (4) + * @arg @ref LL_ADC_CHANNEL_VBAT (4) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2 (5) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC2 (2)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH1_ADC3 (3)(6) + * @arg @ref LL_ADC_CHANNEL_DAC1CH2_ADC3 (3)(6) + * + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3.\n + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances.\n + * (7) On STM32L4, fast channel (0.188 us for 12-bit resolution (ADC conversion rate up to 5.33 Ms/s)). + * Other channels are slow channels (0.238 us for 12-bit resolution (ADC conversion rate up to 4.21 Ms/s)). + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_SAMPLINGTIME_2CYCLES_5 (1) + * @arg @ref LL_ADC_SAMPLINGTIME_6CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_12CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_24CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_47CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_92CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_247CYCLES_5 + * @arg @ref LL_ADC_SAMPLINGTIME_640CYCLES_5 + * + * (1) On some devices, ADC sampling time 2.5 ADC clock cycles + * can be replaced by 3.5 ADC clock cycles. + * Refer to function @ref LL_ADC_SetSamplingTimeCommonConfig(). + */ +__STATIC_INLINE uint32_t LL_ADC_GetChannelSamplingTime(const ADC_TypeDef *ADCx, uint32_t Channel) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->SMPR1, ((Channel & ADC_CHANNEL_SMPRX_REGOFFSET_MASK) + >> ADC_SMPRX_REGOFFSET_POS)); + + return (uint32_t)(READ_BIT(*preg, + ADC_SMPR1_SMP0 + << ((Channel & ADC_CHANNEL_SMPx_BITOFFSET_MASK) >> ADC_CHANNEL_SMPx_BITOFFSET_POS)) + >> ((Channel & ADC_CHANNEL_SMPx_BITOFFSET_MASK) >> ADC_CHANNEL_SMPx_BITOFFSET_POS) + ); +} + +/** + * @brief Set mode single-ended or differential input of the selected + * ADC channel. + * @note Channel ending is on channel scope: independently of channel mapped + * on ADC group regular or injected. + * In differential mode: Differential measurement is carried out + * between the selected channel 'i' (positive input) and + * channel 'i+1' (negative input). Only channel 'i' has to be + * configured, channel 'i+1' is configured automatically. + * @note Refer to Reference Manual to ensure the selected channel is + * available in differential mode. + * For example, internal channels (VrefInt, TempSensor, ...) are + * not available in differential mode. + * @note When configuring a channel 'i' in differential mode, + * the channel 'i+1' is not usable separately. + * @note On STM32L4, channels 16, 17, 18 of ADC1, ADC2, ADC3 (if available) + * are internally fixed to single-ended inputs configuration. + * @note For ADC channels configured in differential mode, both inputs + * should be biased at (Vref+)/2 +/-200mV. + * (Vref+ is the analog voltage reference) + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled. + * @note One or several values can be selected. + * Example: (LL_ADC_CHANNEL_4 | LL_ADC_CHANNEL_12 | ...) + * @rmtoll DIFSEL DIFSEL LL_ADC_SetChannelSingleDiff + * @param ADCx ADC instance + * @param Channel This parameter can be one of the following values: + * @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 + * @param SingleDiff This parameter can be a combination of the following values: + * @arg @ref LL_ADC_SINGLE_ENDED + * @arg @ref LL_ADC_DIFFERENTIAL_ENDED + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetChannelSingleDiff(ADC_TypeDef *ADCx, uint32_t Channel, uint32_t SingleDiff) +{ + /* Bits of channels in single or differential mode are set only for */ + /* differential mode (for single mode, mask of bits allowed to be set is */ + /* shifted out of range of bits of channels in single or differential mode. */ + MODIFY_REG(ADCx->DIFSEL, + Channel & ADC_SINGLEDIFF_CHANNEL_MASK, + (Channel & ADC_SINGLEDIFF_CHANNEL_MASK) + & (ADC_DIFSEL_DIFSEL >> (SingleDiff & ADC_SINGLEDIFF_CHANNEL_SHIFT_MASK))); +} + +/** + * @brief Get mode single-ended or differential input of the selected + * ADC channel. + * @note When configuring a channel 'i' in differential mode, + * the channel 'i+1' is not usable separately. + * Therefore, to ensure a channel is configured in single-ended mode, + * the configuration of channel itself and the channel 'i-1' must be + * read back (to ensure that the selected channel channel has not been + * configured in differential mode by the previous channel). + * @note Refer to Reference Manual to ensure the selected channel is + * available in differential mode. + * For example, internal channels (VrefInt, TempSensor, ...) are + * not available in differential mode. + * @note When configuring a channel 'i' in differential mode, + * the channel 'i+1' is not usable separately. + * @note On STM32L4, channels 16, 17, 18 of ADC1, ADC2, ADC3 (if available) + * are internally fixed to single-ended inputs configuration. + * @note One or several values can be selected. In this case, the value + * returned is null if all channels are in single ended-mode. + * Example: (LL_ADC_CHANNEL_4 | LL_ADC_CHANNEL_12 | ...) + * @rmtoll DIFSEL DIFSEL LL_ADC_GetChannelSingleDiff + * @param ADCx ADC instance + * @param Channel This parameter can be a combination of the following values: + * @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 + * @retval 0: channel in single-ended mode, else: channel in differential mode + */ +__STATIC_INLINE uint32_t LL_ADC_GetChannelSingleDiff(const ADC_TypeDef *ADCx, uint32_t Channel) +{ + return (uint32_t)(READ_BIT(ADCx->DIFSEL, (Channel & ADC_SINGLEDIFF_CHANNEL_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, multiple channels 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 are 2 kinds 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). + * - AWD flexible (instances AWD2, AWD3): + * - channels monitored: flexible on channels monitored, selection is + * channel wise, from from 1 to all channels. + * Specificity of this analog watchdog: Multiple channels can + * be selected. For example: + * (LL_ADC_AWD_CHANNEL4_REG_INJ | LL_ADC_AWD_CHANNEL5_REG_INJ | ...) + * - groups monitored: not selection possible (monitoring on both + * groups regular and injected). + * Channels selected are monitored on groups regular and injected: + * LL_ADC_AWD_CHANNELxx_REG_INJ (do not use parameters + * LL_ADC_AWD_CHANNELxx_REG and LL_ADC_AWD_CHANNELxx_INJ) + * - resolution: resolution is limited to 8 bits: if ADC resolution is + * 12 bits the 4 LSB are ignored, if ADC resolution is 10 bits + * the 2 LSB are ignored. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR AWD1CH LL_ADC_SetAnalogWDMonitChannels\n + * CFGR AWD1SGL LL_ADC_SetAnalogWDMonitChannels\n + * CFGR AWD1EN LL_ADC_SetAnalogWDMonitChannels\n + * CFGR JAWD1EN LL_ADC_SetAnalogWDMonitChannels\n + * AWD2CR AWD2CH LL_ADC_SetAnalogWDMonitChannels\n + * AWD3CR AWD3CH LL_ADC_SetAnalogWDMonitChannels + * @param ADCx ADC instance + * @param AWDy This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD1 + * @arg @ref LL_ADC_AWD2 + * @arg @ref LL_ADC_AWD3 + * @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 (0) + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_INJ (0) + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_0_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_1_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_2_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_3_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_4_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_5_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_6_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_7_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_8_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_9_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_10_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_11_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_12_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_13_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_14_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_15_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_16_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_17_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_18_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG_INJ + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG (0)(1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_INJ (0)(1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG_INJ (1) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG (0)(4) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_INJ (0)(4) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ (4) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG (0)(4) + * @arg @ref LL_ADC_AWD_CH_VBAT_INJ (0)(4) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG_INJ (4) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_REG (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_INJ (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_REG_INJ (2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_REG (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_INJ (0)(2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_REG_INJ (2)(5) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC2_REG (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC2_INJ (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC2_REG_INJ (2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC2_REG (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC2_INJ (0)(2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC2_REG_INJ (2)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC3_REG (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC3_INJ (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH1_ADC3_REG_INJ (3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC3_REG (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC3_INJ (0)(3)(6) + * @arg @ref LL_ADC_AWD_CH_DAC1CH2_ADC3_REG_INJ (3)(6) + * + * (0) On STM32L4, parameter available only on analog watchdog number: AWD1.\n + * (1) On STM32L4, parameter available only on ADC instance: ADC1.\n + * (2) On STM32L4, parameter available only on ADC instance: ADC2.\n + * (3) On STM32L4, parameter available only on ADC instance: ADC3.\n + * (4) On STM32L4, parameter available only on ADC instances: ADC1, ADC3. + * (5) On STM32L4, parameter available on devices with only 1 ADC instance.\n + * (6) On STM32L4, parameter available on devices with several ADC instances. + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetAnalogWDMonitChannels(ADC_TypeDef *ADCx, uint32_t AWDy, uint32_t AWDChannelGroup) +{ + /* Set bits with content of parameter "AWDChannelGroup" with bits position */ + /* in register and register position depending on parameter "AWDy". */ + /* Parameters "AWDChannelGroup" and "AWDy" are used with masks because */ + /* containing other bits reserved for other purpose. */ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->CFGR, + ((AWDy & ADC_AWD_CRX_REGOFFSET_MASK) >> ADC_AWD_CRX_REGOFFSET_POS) + + ((AWDy & ADC_AWD_CR12_REGOFFSETGAP_MASK) + * ADC_AWD_CR12_REGOFFSETGAP_VAL)); + + MODIFY_REG(*preg, + (AWDy & ADC_AWD_CR_ALL_CHANNEL_MASK), + AWDChannelGroup & AWDy); +} + +/** + * @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 are 2 kinds 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). + * - AWD flexible (instances AWD2, AWD3): + * - channels monitored: flexible on channels monitored, selection is + * channel wise, from from 1 to all channels. + * Specificity of this analog watchdog: Multiple channels can + * be selected. For example: + * (LL_ADC_AWD_CHANNEL4_REG_INJ | LL_ADC_AWD_CHANNEL5_REG_INJ | ...) + * - groups monitored: not selection possible (monitoring on both + * groups regular and injected). + * Channels selected are monitored on groups regular and injected: + * LL_ADC_AWD_CHANNELxx_REG_INJ (do not use parameters + * LL_ADC_AWD_CHANNELxx_REG and LL_ADC_AWD_CHANNELxx_INJ) + * - resolution: resolution is limited to 8 bits: if ADC resolution is + * 12 bits the 4 LSB are ignored, if ADC resolution is 10 bits + * the 2 LSB are ignored. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR AWD1CH LL_ADC_GetAnalogWDMonitChannels\n + * CFGR AWD1SGL LL_ADC_GetAnalogWDMonitChannels\n + * CFGR AWD1EN LL_ADC_GetAnalogWDMonitChannels\n + * CFGR JAWD1EN LL_ADC_GetAnalogWDMonitChannels\n + * AWD2CR AWD2CH LL_ADC_GetAnalogWDMonitChannels\n + * AWD3CR AWD3CH LL_ADC_GetAnalogWDMonitChannels + * @param ADCx ADC instance + * @param AWDy This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD1 + * @arg @ref LL_ADC_AWD2 (1) + * @arg @ref LL_ADC_AWD3 (1) + * + * (1) On this AWD number, monitored channel can be retrieved + * if only 1 channel is programmed (or none or all channels). + * This function cannot retrieve monitored channel if + * multiple channels are programmed simultaneously + * by bitfield. + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_AWD_DISABLE + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG (0) + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_INJ (0) + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_0_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_1_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_2_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_3_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_4_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_5_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_6_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_7_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_8_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_9_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_10_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_11_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_12_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_13_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_14_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_15_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_16_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_17_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG (0) + * @arg @ref LL_ADC_AWD_CHANNEL_18_INJ (0) + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG_INJ + * + * (0) On STM32L4, parameter available only on analog watchdog number: AWD1. + */ +__STATIC_INLINE uint32_t LL_ADC_GetAnalogWDMonitChannels(const ADC_TypeDef *ADCx, uint32_t AWDy) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->CFGR, + ((AWDy & ADC_AWD_CRX_REGOFFSET_MASK) >> ADC_AWD_CRX_REGOFFSET_POS) + + ((AWDy & ADC_AWD_CR12_REGOFFSETGAP_MASK) + * ADC_AWD_CR12_REGOFFSETGAP_VAL)); + + uint32_t analog_wd_monit_channels = (READ_BIT(*preg, AWDy) & AWDy & ADC_AWD_CR_ALL_CHANNEL_MASK); + + /* If "analog_wd_monit_channels" == 0, then the selected AWD is disabled */ + /* (parameter value LL_ADC_AWD_DISABLE). */ + /* Else, the selected AWD is enabled and is monitoring a group of channels */ + /* or a single channel. */ + if (analog_wd_monit_channels != 0UL) + { + if (AWDy == LL_ADC_AWD1) + { + if ((analog_wd_monit_channels & ADC_CFGR_AWD1SGL) == 0UL) + { + /* AWD monitoring a group of channels */ + analog_wd_monit_channels = ((analog_wd_monit_channels + | (ADC_AWD_CR23_CHANNEL_MASK) + ) + & (~(ADC_CFGR_AWD1CH)) + ); + } + else + { + /* AWD monitoring a single channel */ + analog_wd_monit_channels = (analog_wd_monit_channels + | (ADC_AWD2CR_AWD2CH_0 << (analog_wd_monit_channels >> ADC_CFGR_AWD1CH_Pos)) + ); + } + } + else + { + if ((analog_wd_monit_channels & ADC_AWD_CR23_CHANNEL_MASK) == ADC_AWD_CR23_CHANNEL_MASK) + { + /* AWD monitoring a group of channels */ + analog_wd_monit_channels = (ADC_AWD_CR23_CHANNEL_MASK + | ((ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN)) + ); + } + else + { + /* AWD monitoring a single channel */ + /* AWD monitoring a group of channels */ + analog_wd_monit_channels = (analog_wd_monit_channels + | (ADC_CFGR_JAWD1EN | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL) + | (__LL_ADC_CHANNEL_TO_DECIMAL_NB(analog_wd_monit_channels) << ADC_CFGR_AWD1CH_Pos) + ); + } + } + } + + return analog_wd_monit_channels; +} + +/** + * @brief Set ADC analog watchdog thresholds value of both thresholds + * high and low. + * @note If value of only one threshold high or low must be set, + * use function @ref LL_ADC_SetAnalogWDThresholds(). + * @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 are 2 kinds 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). + * - AWD flexible (instances AWD2, AWD3): + * - channels monitored: flexible on channels monitored, selection is + * channel wise, from from 1 to all channels. + * Specificity of this analog watchdog: Multiple channels can + * be selected. For example: + * (LL_ADC_AWD_CHANNEL4_REG_INJ | LL_ADC_AWD_CHANNEL5_REG_INJ | ...) + * - groups monitored: not selection possible (monitoring on both + * groups regular and injected). + * Channels selected are monitored on groups regular and injected: + * LL_ADC_AWD_CHANNELxx_REG_INJ (do not use parameters + * LL_ADC_AWD_CHANNELxx_REG and LL_ADC_AWD_CHANNELxx_INJ) + * - resolution: resolution is limited to 8 bits: if ADC resolution is + * 12 bits the 4 LSB are ignored, if ADC resolution is 10 bits + * the 2 LSB are ignored. + * @note If ADC oversampling is enabled, ADC analog watchdog thresholds are + * impacted: the comparison of analog watchdog thresholds is done on + * oversampling final computation (after ratio and shift application): + * ADC data register bitfield [15:4] (12 most significant bits). + * Examples: + * - Oversampling ratio and shift selected to have ADC conversion data + * on 12 bits (ratio 16 and shift 4, or ratio 32 and shift 5, ...): + * ADC analog watchdog thresholds must be divided by 16. + * - Oversampling ratio and shift selected to have ADC conversion data + * on 14 bits (ratio 16 and shift 2, or ratio 32 and shift 3, ...): + * ADC analog watchdog thresholds must be divided by 4. + * - Oversampling ratio and shift selected to have ADC conversion data + * on 16 bits (ratio 16 and shift none, or ratio 32 and shift 1, ...): + * ADC analog watchdog thresholds match directly to ADC data register. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll TR1 HT1 LL_ADC_ConfigAnalogWDThresholds\n + * TR2 HT2 LL_ADC_ConfigAnalogWDThresholds\n + * TR3 HT3 LL_ADC_ConfigAnalogWDThresholds\n + * TR1 LT1 LL_ADC_ConfigAnalogWDThresholds\n + * TR2 LT2 LL_ADC_ConfigAnalogWDThresholds\n + * TR3 LT3 LL_ADC_ConfigAnalogWDThresholds + * @param ADCx ADC instance + * @param AWDy This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD1 + * @arg @ref LL_ADC_AWD2 + * @arg @ref LL_ADC_AWD3 + * @param AWDThresholdHighValue Value between Min_Data=0x000 and Max_Data=0xFFF + * @param AWDThresholdLowValue Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_ADC_ConfigAnalogWDThresholds(ADC_TypeDef *ADCx, uint32_t AWDy, uint32_t AWDThresholdHighValue, + uint32_t AWDThresholdLowValue) +{ + /* Set bits with content of parameter "AWDThresholdxxxValue" with bits */ + /* position in register and register position depending on parameter */ + /* "AWDy". */ + /* Parameters "AWDy" and "AWDThresholdxxxValue" are used with masks because */ + /* containing other bits reserved for other purpose. */ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->TR1, + ((AWDy & ADC_AWD_TRX_REGOFFSET_MASK) >> ADC_AWD_TRX_REGOFFSET_POS)); + + MODIFY_REG(*preg, + ADC_TR1_HT1 | ADC_TR1_LT1, + (AWDThresholdHighValue << ADC_TR1_HT1_BITOFFSET_POS) | AWDThresholdLowValue); +} + +/** + * @brief Set ADC analog watchdog threshold value of threshold + * high or low. + * @note If values of both thresholds high or low must be set, + * use function @ref LL_ADC_ConfigAnalogWDThresholds(). + * @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 are 2 kinds 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). + * - AWD flexible (instances AWD2, AWD3): + * - channels monitored: flexible on channels monitored, selection is + * channel wise, from from 1 to all channels. + * Specificity of this analog watchdog: Multiple channels can + * be selected. For example: + * (LL_ADC_AWD_CHANNEL4_REG_INJ | LL_ADC_AWD_CHANNEL5_REG_INJ | ...) + * - groups monitored: not selection possible (monitoring on both + * groups regular and injected). + * Channels selected are monitored on groups regular and injected: + * LL_ADC_AWD_CHANNELxx_REG_INJ (do not use parameters + * LL_ADC_AWD_CHANNELxx_REG and LL_ADC_AWD_CHANNELxx_INJ) + * - resolution: resolution is limited to 8 bits: if ADC resolution is + * 12 bits the 4 LSB are ignored, if ADC resolution is 10 bits + * the 2 LSB are ignored. + * @note If ADC oversampling is enabled, ADC analog watchdog thresholds are + * impacted: the comparison of analog watchdog thresholds is done on + * oversampling final computation (after ratio and shift application): + * ADC data register bitfield [15:4] (12 most significant bits). + * Examples: + * - Oversampling ratio and shift selected to have ADC conversion data + * on 12 bits (ratio 16 and shift 4, or ratio 32 and shift 5, ...): + * ADC analog watchdog thresholds must be divided by 16. + * - Oversampling ratio and shift selected to have ADC conversion data + * on 14 bits (ratio 16 and shift 2, or ratio 32 and shift 3, ...): + * ADC analog watchdog thresholds must be divided by 4. + * - Oversampling ratio and shift selected to have ADC conversion data + * on 16 bits (ratio 16 and shift none, or ratio 32 and shift 1, ...): + * ADC analog watchdog thresholds match directly to ADC data register. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either ADC groups regular or injected. + * @rmtoll TR1 HT1 LL_ADC_SetAnalogWDThresholds\n + * TR2 HT2 LL_ADC_SetAnalogWDThresholds\n + * TR3 HT3 LL_ADC_SetAnalogWDThresholds\n + * TR1 LT1 LL_ADC_SetAnalogWDThresholds\n + * TR2 LT2 LL_ADC_SetAnalogWDThresholds\n + * TR3 LT3 LL_ADC_SetAnalogWDThresholds + * @param ADCx ADC instance + * @param AWDy This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD1 + * @arg @ref LL_ADC_AWD2 + * @arg @ref LL_ADC_AWD3 + * @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 AWDy, uint32_t AWDThresholdsHighLow, + uint32_t AWDThresholdValue) +{ + /* Set bits with content of parameter "AWDThresholdValue" with bits */ + /* position in register and register position depending on parameters */ + /* "AWDThresholdsHighLow" and "AWDy". */ + /* Parameters "AWDy" and "AWDThresholdValue" are used with masks because */ + /* containing other bits reserved for other purpose. */ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->TR1, + ((AWDy & ADC_AWD_TRX_REGOFFSET_MASK) >> ADC_AWD_TRX_REGOFFSET_POS)); + + MODIFY_REG(*preg, + AWDThresholdsHighLow, + AWDThresholdValue << ((AWDThresholdsHighLow & ADC_AWD_TRX_BIT_HIGH_MASK) >> ADC_AWD_TRX_BIT_HIGH_SHIFT4)); +} + +/** + * @brief Get ADC analog watchdog threshold value of threshold high, + * threshold low or raw data with ADC thresholds high and low + * concatenated. + * @note If raw data with ADC thresholds high and low is retrieved, + * the data of each threshold high or low can be isolated + * using helper macro: + * @ref __LL_ADC_ANALOGWD_THRESHOLDS_HIGH_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 TR1 HT1 LL_ADC_GetAnalogWDThresholds\n + * TR2 HT2 LL_ADC_GetAnalogWDThresholds\n + * TR3 HT3 LL_ADC_GetAnalogWDThresholds\n + * TR1 LT1 LL_ADC_GetAnalogWDThresholds\n + * TR2 LT2 LL_ADC_GetAnalogWDThresholds\n + * TR3 LT3 LL_ADC_GetAnalogWDThresholds + * @param ADCx ADC instance + * @param AWDy This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD1 + * @arg @ref LL_ADC_AWD2 + * @arg @ref LL_ADC_AWD3 + * @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 + * @arg @ref LL_ADC_AWD_THRESHOLDS_HIGH_LOW + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_ADC_GetAnalogWDThresholds(const ADC_TypeDef *ADCx, + uint32_t AWDy, uint32_t AWDThresholdsHighLow) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->TR1, + ((AWDy & ADC_AWD_TRX_REGOFFSET_MASK) >> ADC_AWD_TRX_REGOFFSET_POS)); + + return (uint32_t)(READ_BIT(*preg, + (AWDThresholdsHighLow | ADC_TR1_LT1)) + >> (((AWDThresholdsHighLow & ADC_AWD_TRX_BIT_HIGH_MASK) >> ADC_AWD_TRX_BIT_HIGH_SHIFT4) + & ~(AWDThresholdsHighLow & ADC_TR1_LT1))); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_oversampling Configuration of ADC transversal scope: oversampling + * @{ + */ + +/** + * @brief Set ADC oversampling scope: ADC groups regular and-or injected + * (availability of ADC group injected depends on STM32 series). + * @note If both groups regular and injected are selected, + * specify behavior of ADC group injected interrupting + * group regular: when ADC group injected is triggered, + * the oversampling on ADC group regular is either + * temporary stopped and continued, or resumed from start + * (oversampler buffer reset). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR2 ROVSE LL_ADC_SetOverSamplingScope\n + * CFGR2 JOVSE LL_ADC_SetOverSamplingScope\n + * CFGR2 ROVSM LL_ADC_SetOverSamplingScope + * @param ADCx ADC instance + * @param OvsScope This parameter can be one of the following values: + * @arg @ref LL_ADC_OVS_DISABLE + * @arg @ref LL_ADC_OVS_GRP_REGULAR_CONTINUED + * @arg @ref LL_ADC_OVS_GRP_REGULAR_RESUMED + * @arg @ref LL_ADC_OVS_GRP_INJECTED + * @arg @ref LL_ADC_OVS_GRP_INJ_REG_RESUMED + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetOverSamplingScope(ADC_TypeDef *ADCx, uint32_t OvsScope) +{ + MODIFY_REG(ADCx->CFGR2, ADC_CFGR2_ROVSE | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSM, OvsScope); +} + +/** + * @brief Get ADC oversampling scope: ADC groups regular and-or injected + * (availability of ADC group injected depends on STM32 series). + * @note If both groups regular and injected are selected, + * specify behavior of ADC group injected interrupting + * group regular: when ADC group injected is triggered, + * the oversampling on ADC group regular is either + * temporary stopped and continued, or resumed from start + * (oversampler buffer reset). + * @rmtoll CFGR2 ROVSE LL_ADC_GetOverSamplingScope\n + * CFGR2 JOVSE LL_ADC_GetOverSamplingScope\n + * CFGR2 ROVSM LL_ADC_GetOverSamplingScope + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_OVS_DISABLE + * @arg @ref LL_ADC_OVS_GRP_REGULAR_CONTINUED + * @arg @ref LL_ADC_OVS_GRP_REGULAR_RESUMED + * @arg @ref LL_ADC_OVS_GRP_INJECTED + * @arg @ref LL_ADC_OVS_GRP_INJ_REG_RESUMED + */ +__STATIC_INLINE uint32_t LL_ADC_GetOverSamplingScope(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR2, ADC_CFGR2_ROVSE | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSM)); +} + +/** + * @brief Set ADC oversampling discontinuous mode (triggered mode) + * on the selected ADC group. + * @note Number of oversampled conversions are done either in: + * - continuous mode (all conversions of oversampling ratio + * are done from 1 trigger) + * - discontinuous mode (each conversion of oversampling ratio + * needs a trigger) + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on group regular. + * @note On this STM32 series, oversampling discontinuous mode + * (triggered mode) can be used only when oversampling is + * set on group regular only and in resumed mode. + * @rmtoll CFGR2 TROVS LL_ADC_SetOverSamplingDiscont + * @param ADCx ADC instance + * @param OverSamplingDiscont This parameter can be one of the following values: + * @arg @ref LL_ADC_OVS_REG_CONT + * @arg @ref LL_ADC_OVS_REG_DISCONT + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetOverSamplingDiscont(ADC_TypeDef *ADCx, uint32_t OverSamplingDiscont) +{ + MODIFY_REG(ADCx->CFGR2, ADC_CFGR2_TROVS, OverSamplingDiscont); +} + +/** + * @brief Get ADC oversampling discontinuous mode (triggered mode) + * on the selected ADC group. + * @note Number of oversampled conversions are done either in: + * - continuous mode (all conversions of oversampling ratio + * are done from 1 trigger) + * - discontinuous mode (each conversion of oversampling ratio + * needs a trigger) + * @rmtoll CFGR2 TROVS LL_ADC_GetOverSamplingDiscont + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_OVS_REG_CONT + * @arg @ref LL_ADC_OVS_REG_DISCONT + */ +__STATIC_INLINE uint32_t LL_ADC_GetOverSamplingDiscont(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR2, ADC_CFGR2_TROVS)); +} + +/** + * @brief Set ADC oversampling + * (impacting both ADC groups regular and injected) + * @note This function set the 2 items of oversampling configuration: + * - ratio + * - shift + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be disabled or enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CFGR2 OVSS LL_ADC_ConfigOverSamplingRatioShift\n + * CFGR2 OVSR LL_ADC_ConfigOverSamplingRatioShift + * @param ADCx ADC instance + * @param Ratio This parameter can be one of the following values: + * @arg @ref LL_ADC_OVS_RATIO_2 + * @arg @ref LL_ADC_OVS_RATIO_4 + * @arg @ref LL_ADC_OVS_RATIO_8 + * @arg @ref LL_ADC_OVS_RATIO_16 + * @arg @ref LL_ADC_OVS_RATIO_32 + * @arg @ref LL_ADC_OVS_RATIO_64 + * @arg @ref LL_ADC_OVS_RATIO_128 + * @arg @ref LL_ADC_OVS_RATIO_256 + * @param Shift This parameter can be one of the following values: + * @arg @ref LL_ADC_OVS_SHIFT_NONE + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_1 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_2 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_3 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_4 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_5 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_6 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_7 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_8 + * @retval None + */ +__STATIC_INLINE void LL_ADC_ConfigOverSamplingRatioShift(ADC_TypeDef *ADCx, uint32_t Ratio, uint32_t Shift) +{ + MODIFY_REG(ADCx->CFGR2, (ADC_CFGR2_OVSS | ADC_CFGR2_OVSR), (Shift | Ratio)); +} + +/** + * @brief Get ADC oversampling ratio + * (impacting both ADC groups regular and injected) + * @rmtoll CFGR2 OVSR LL_ADC_GetOverSamplingRatio + * @param ADCx ADC instance + * @retval Ratio This parameter can be one of the following values: + * @arg @ref LL_ADC_OVS_RATIO_2 + * @arg @ref LL_ADC_OVS_RATIO_4 + * @arg @ref LL_ADC_OVS_RATIO_8 + * @arg @ref LL_ADC_OVS_RATIO_16 + * @arg @ref LL_ADC_OVS_RATIO_32 + * @arg @ref LL_ADC_OVS_RATIO_64 + * @arg @ref LL_ADC_OVS_RATIO_128 + * @arg @ref LL_ADC_OVS_RATIO_256 + */ +__STATIC_INLINE uint32_t LL_ADC_GetOverSamplingRatio(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR2, ADC_CFGR2_OVSR)); +} + +/** + * @brief Get ADC oversampling shift + * (impacting both ADC groups regular and injected) + * @rmtoll CFGR2 OVSS LL_ADC_GetOverSamplingShift + * @param ADCx ADC instance + * @retval Shift This parameter can be one of the following values: + * @arg @ref LL_ADC_OVS_SHIFT_NONE + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_1 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_2 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_3 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_4 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_5 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_6 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_7 + * @arg @ref LL_ADC_OVS_SHIFT_RIGHT_8 + */ +__STATIC_INLINE uint32_t LL_ADC_GetOverSamplingShift(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CFGR2, ADC_CFGR2_OVSS)); +} + +/** + * @} + */ + +/** @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. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * All ADC instances of the ADC common group must be disabled. + * This check can be done with function @ref LL_ADC_IsEnabled() for each + * ADC instance or by using helper macro + * @ref __LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(). + * @rmtoll CCR DUAL 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 + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetMultimode(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t Multimode) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_DUAL, 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 DUAL 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 + */ +__STATIC_INLINE uint32_t LL_ADC_GetMultimode(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_DUAL)); +} + +/** + * @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(). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * All ADC instances of the ADC common group must be disabled + * or enabled without conversion on going on group regular. + * @rmtoll CCR MDMA LL_ADC_SetMultiDMATransfer\n + * CCR DMACFG 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_RES12_10B + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_RES8_6B + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_RES12_10B + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_RES8_6B + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetMultiDMATransfer(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t MultiDMATransfer) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_MDMA | ADC_CCR_DMACFG, 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 DMACFG 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_RES12_10B + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_RES8_6B + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_RES12_10B + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_RES8_6B + */ +__STATIC_INLINE uint32_t LL_ADC_GetMultiDMATransfer(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_MDMA | ADC_CCR_DMACFG)); +} + +/** + * @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. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * All ADC instances of the ADC common group must be disabled. + * This check can be done with function @ref LL_ADC_IsEnabled() for each + * ADC instance or by using helper macro helper macro + * @ref __LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(). + * @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_1CYCLE + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_2CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_3CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_4CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES (1) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES (1) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES (2) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES (2) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES (2) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_11CYCLES (3) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_12CYCLES (3) + * + * (1) Parameter available only if ADC resolution is 12, 10 or 8 bits.\n + * (2) Parameter available only if ADC resolution is 12 or 10 bits.\n + * (3) Parameter available only if ADC resolution is 12 bits. + * @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_1CYCLE + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_2CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_3CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_4CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES (1) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES (1) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES (2) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES (2) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES (2) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_11CYCLES (3) + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_12CYCLES (3) + * + * (1) Parameter available only if ADC resolution is 12, 10 or 8 bits.\n + * (2) Parameter available only if ADC resolution is 12 or 10 bits.\n + * (3) Parameter available only if ADC resolution is 12 bits. + */ +__STATIC_INLINE uint32_t LL_ADC_GetMultiTwoSamplingDelay(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_DELAY)); +} +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @} + */ +/** @defgroup ADC_LL_EF_Configuration_Leg_Functions Configuration of ADC alternate functions name + * @{ + */ +/* Old functions name kept for legacy purpose, to be replaced by the */ +/* current functions name. */ +__STATIC_INLINE void LL_ADC_REG_SetTrigSource(ADC_TypeDef *ADCx, uint32_t TriggerSource) +{ + LL_ADC_REG_SetTriggerSource(ADCx, TriggerSource); +} +__STATIC_INLINE void LL_ADC_INJ_SetTrigSource(ADC_TypeDef *ADCx, uint32_t TriggerSource) +{ + LL_ADC_INJ_SetTriggerSource(ADCx, TriggerSource); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Operation_ADC_Instance Operation on ADC hierarchical scope: ADC instance + * @{ + */ + +/** + * @brief Put ADC instance in deep power down state. + * @note In case of ADC calibration necessary: When ADC is in deep-power-down + * state, the internal analog calibration is lost. After exiting from + * deep power down, calibration must be relaunched or calibration factor + * (preliminarily saved) must be set back into calibration register. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled. + * @rmtoll CR DEEPPWD LL_ADC_EnableDeepPowerDown + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableDeepPowerDown(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_DEEPPWD); +} + +/** + * @brief Disable ADC deep power down mode. + * @note In case of ADC calibration necessary: When ADC is in deep-power-down + * state, the internal analog calibration is lost. After exiting from + * deep power down, calibration must be relaunched or calibration factor + * (preliminarily saved) must be set back into calibration register. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled. + * @rmtoll CR DEEPPWD LL_ADC_DisableDeepPowerDown + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableDeepPowerDown(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + CLEAR_BIT(ADCx->CR, (ADC_CR_DEEPPWD | ADC_CR_BITS_PROPERTY_RS)); +} + +/** + * @brief Get the selected ADC instance deep power down state. + * @rmtoll CR DEEPPWD LL_ADC_IsDeepPowerDownEnabled + * @param ADCx ADC instance + * @retval 0: deep power down is disabled, 1: deep power down is enabled. + */ +__STATIC_INLINE uint32_t LL_ADC_IsDeepPowerDownEnabled(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_DEEPPWD) == (ADC_CR_DEEPPWD)) ? 1UL : 0UL); +} + +/** + * @brief Enable ADC instance internal voltage regulator. + * @note On this STM32 series, after ADC internal voltage regulator enable, + * a delay for ADC internal voltage regulator stabilization + * is required before performing a ADC calibration or ADC enable. + * Refer to device datasheet, parameter tADCVREG_STUP. + * Refer to literal @ref LL_ADC_DELAY_INTERNAL_REGUL_STAB_US. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled. + * @rmtoll CR ADVREGEN LL_ADC_EnableInternalRegulator + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableInternalRegulator(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_ADVREGEN); +} + +/** + * @brief Disable ADC internal voltage regulator. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled. + * @rmtoll CR ADVREGEN LL_ADC_DisableInternalRegulator + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableInternalRegulator(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR, (ADC_CR_ADVREGEN | ADC_CR_BITS_PROPERTY_RS)); +} + +/** + * @brief Get the selected ADC instance internal voltage regulator state. + * @rmtoll CR ADVREGEN LL_ADC_IsInternalRegulatorEnabled + * @param ADCx ADC instance + * @retval 0: internal regulator is disabled, 1: internal regulator is enabled. + */ +__STATIC_INLINE uint32_t LL_ADC_IsInternalRegulatorEnabled(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_ADVREGEN) == (ADC_CR_ADVREGEN)) ? 1UL : 0UL); +} + +/** + * @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. + * @note On this STM32 series, flag LL_ADC_FLAG_ADRDY is raised when the ADC + * is enabled and when conversion clock is active. + * (not only core clock: this ADC has a dual clock domain) + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled and ADC internal voltage regulator enabled. + * @rmtoll CR ADEN LL_ADC_Enable + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_Enable(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_ADEN); +} + +/** + * @brief Disable the selected ADC instance. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be not disabled. Must be enabled without conversion on going + * on either groups regular or injected. + * @rmtoll CR ADDIS LL_ADC_Disable + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_Disable(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_ADDIS); +} + +/** + * @brief Get the selected ADC instance enable state. + * @note On this STM32 series, flag LL_ADC_FLAG_ADRDY is raised when the ADC + * is enabled and when conversion clock is active. + * (not only core clock: this ADC has a dual clock domain) + * @rmtoll CR ADEN LL_ADC_IsEnabled + * @param ADCx ADC instance + * @retval 0: ADC is disabled, 1: ADC is enabled. + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabled(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_ADEN) == (ADC_CR_ADEN)) ? 1UL : 0UL); +} + +/** + * @brief Get the selected ADC instance disable state. + * @rmtoll CR ADDIS LL_ADC_IsDisableOngoing + * @param ADCx ADC instance + * @retval 0: no ADC disable command on going. + */ +__STATIC_INLINE uint32_t LL_ADC_IsDisableOngoing(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_ADDIS) == (ADC_CR_ADDIS)) ? 1UL : 0UL); +} + +/** + * @brief Start ADC calibration in the mode single-ended + * or differential (for devices with differential mode available). + * @note On this STM32 series, a minimum number of ADC clock cycles + * are required between ADC end of calibration and ADC enable. + * Refer to literal @ref LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES. + * @note For devices with differential mode available: + * Calibration of offset is specific to each of + * single-ended and differential modes + * (calibration run must be performed for each of these + * differential modes, if used afterwards and if the application + * requires their calibration). + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be ADC disabled. + * @rmtoll CR ADCAL LL_ADC_StartCalibration\n + * CR ADCALDIF LL_ADC_StartCalibration + * @param ADCx ADC instance + * @param SingleDiff This parameter can be one of the following values: + * @arg @ref LL_ADC_SINGLE_ENDED + * @arg @ref LL_ADC_DIFFERENTIAL_ENDED + * @retval None + */ +__STATIC_INLINE void LL_ADC_StartCalibration(ADC_TypeDef *ADCx, uint32_t SingleDiff) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_ADCALDIF | ADC_CR_BITS_PROPERTY_RS, + ADC_CR_ADCAL | (SingleDiff & ADC_SINGLEDIFF_CALIB_START_MASK)); +} + +/** + * @brief Get ADC calibration state. + * @rmtoll CR ADCAL LL_ADC_IsCalibrationOnGoing + * @param ADCx ADC instance + * @retval 0: calibration complete, 1: calibration in progress. + */ +__STATIC_INLINE uint32_t LL_ADC_IsCalibrationOnGoing(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_ADCAL) == (ADC_CR_ADCAL)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @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 for both + * internal trigger (SW start) and 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 + * will start at next trigger event (on the selected trigger edge) + * following the ADC start conversion command. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be enabled without conversion on going on group regular, + * without conversion stop command on going on group regular, + * without ADC disable command on going. + * @rmtoll CR ADSTART LL_ADC_REG_StartConversion + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_StartConversion(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_ADSTART); +} + +/** + * @brief Stop ADC group regular conversion. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be enabled with conversion on going on group regular, + * without ADC disable command on going. + * @rmtoll CR ADSTP LL_ADC_REG_StopConversion + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_StopConversion(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_ADSTP); +} + +/** + * @brief Get ADC group regular conversion state. + * @rmtoll CR ADSTART LL_ADC_REG_IsConversionOngoing + * @param ADCx ADC instance + * @retval 0: no conversion is on going on ADC group regular. + */ +__STATIC_INLINE uint32_t LL_ADC_REG_IsConversionOngoing(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_ADSTART) == (ADC_CR_ADSTART)) ? 1UL : 0UL); +} + +/** + * @brief Get ADC group regular command of conversion stop state + * @rmtoll CR ADSTP LL_ADC_REG_IsStopConversionOngoing + * @param ADCx ADC instance + * @retval 0: no command of conversion stop is on going on ADC group regular. + */ +__STATIC_INLINE uint32_t LL_ADC_REG_IsStopConversionOngoing(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_ADSTP) == (ADC_CR_ADSTP)) ? 1UL : 0UL); +} + +/** + * @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(const ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->DR, ADC_DR_RDATA)); +} + +/** + * @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(const ADC_TypeDef *ADCx) +{ + return (uint16_t)(READ_BIT(ADCx->DR, ADC_DR_RDATA)); +} + +/** + * @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(const ADC_TypeDef *ADCx) +{ + return (uint16_t)(READ_BIT(ADCx->DR, ADC_DR_RDATA)); +} + +/** + * @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(const ADC_TypeDef *ADCx) +{ + return (uint8_t)(READ_BIT(ADCx->DR, ADC_DR_RDATA)); +} + +/** + * @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(const ADC_TypeDef *ADCx) +{ + return (uint8_t)(READ_BIT(ADCx->DR, ADC_DR_RDATA)); +} + +#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 RDATA_MST LL_ADC_REG_ReadMultiConversionData32\n + * CDR RDATA_SLV 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(const ADC_Common_TypeDef *ADCxy_COMMON, + uint32_t ConversionData) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CDR, + ConversionData) + >> (POSITION_VAL(ConversionData) & 0x1FUL) + ); +} +#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 for both + * internal trigger (SW start) and 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 + * will start at next trigger event (on the selected trigger edge) + * following the ADC start conversion command. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be enabled without conversion on going on group injected, + * without conversion stop command on going on group injected, + * without ADC disable command on going. + * @rmtoll CR JADSTART LL_ADC_INJ_StartConversion + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_StartConversion(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_JADSTART); +} + +/** + * @brief Stop ADC group injected conversion. + * @note On this STM32 series, setting of this feature is conditioned to + * ADC state: + * ADC must be enabled with conversion on going on group injected, + * without ADC disable command on going. + * @rmtoll CR JADSTP LL_ADC_INJ_StopConversion + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_StopConversion(ADC_TypeDef *ADCx) +{ + /* Note: Write register with some additional bits forced to state reset */ + /* instead of modifying only the selected bit for this function, */ + /* to not interfere with bits with HW property "rs". */ + MODIFY_REG(ADCx->CR, + ADC_CR_BITS_PROPERTY_RS, + ADC_CR_JADSTP); +} + +/** + * @brief Get ADC group injected conversion state. + * @rmtoll CR JADSTART LL_ADC_INJ_IsConversionOngoing + * @param ADCx ADC instance + * @retval 0: no conversion is on going on ADC group injected. + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_IsConversionOngoing(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_JADSTART) == (ADC_CR_JADSTART)) ? 1UL : 0UL); +} + +/** + * @brief Get ADC group injected command of conversion stop state + * @rmtoll CR JADSTP LL_ADC_INJ_IsStopConversionOngoing + * @param ADCx ADC instance + * @retval 0: no command of conversion stop is on going on ADC group injected. + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_IsStopConversionOngoing(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->CR, ADC_CR_JADSTP) == (ADC_CR_JADSTP)) ? 1UL : 0UL); +} + +/** + * @brief Get ADC group injected 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, + ((Rank & ADC_INJ_JDRX_REGOFFSET_MASK) >> ADC_JDRX_REGOFFSET_POS)); + + 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, + ((Rank & ADC_INJ_JDRX_REGOFFSET_MASK) >> ADC_JDRX_REGOFFSET_POS)); + + 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, + ((Rank & ADC_INJ_JDRX_REGOFFSET_MASK) >> ADC_JDRX_REGOFFSET_POS)); + + 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, + ((Rank & ADC_INJ_JDRX_REGOFFSET_MASK) >> ADC_JDRX_REGOFFSET_POS)); + + 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(const ADC_TypeDef *ADCx, uint32_t Rank) +{ + const __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, + ((Rank & ADC_INJ_JDRX_REGOFFSET_MASK) >> ADC_JDRX_REGOFFSET_POS)); + + return (uint8_t)(READ_BIT(*preg, + ADC_JDR1_JDATA) + ); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_FLAG_Management ADC flag management + * @{ + */ + +/** + * @brief Get flag ADC ready. + * @note On this STM32 series, flag LL_ADC_FLAG_ADRDY is raised when the ADC + * is enabled and when conversion clock is active. + * (not only core clock: this ADC has a dual clock domain) + * @rmtoll ISR ADRDY LL_ADC_IsActiveFlag_ADRDY + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_ADRDY(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_ADRDY) == (LL_ADC_FLAG_ADRDY)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group regular end of unitary conversion. + * @rmtoll ISR EOC LL_ADC_IsActiveFlag_EOC + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_EOC(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, ADC_ISR_EOC) == (ADC_ISR_EOC)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group regular end of sequence conversions. + * @rmtoll ISR EOS LL_ADC_IsActiveFlag_EOS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_EOS(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_EOS) == (LL_ADC_FLAG_EOS)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group regular overrun. + * @rmtoll ISR OVR LL_ADC_IsActiveFlag_OVR + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_OVR(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_OVR) == (LL_ADC_FLAG_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group regular end of sampling phase. + * @rmtoll ISR EOSMP LL_ADC_IsActiveFlag_EOSMP + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_EOSMP(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_EOSMP) == (LL_ADC_FLAG_EOSMP)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group injected end of unitary conversion. + * @rmtoll ISR JEOC LL_ADC_IsActiveFlag_JEOC + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_JEOC(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_JEOC) == (LL_ADC_FLAG_JEOC)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group injected end of sequence conversions. + * @rmtoll ISR JEOS LL_ADC_IsActiveFlag_JEOS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_JEOS(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_JEOS) == (LL_ADC_FLAG_JEOS)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC group injected contexts queue overflow. + * @rmtoll ISR JQOVF LL_ADC_IsActiveFlag_JQOVF + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_JQOVF(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_JQOVF) == (LL_ADC_FLAG_JQOVF)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC analog watchdog 1 flag + * @rmtoll ISR AWD1 LL_ADC_IsActiveFlag_AWD1 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_AWD1(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_AWD1) == (LL_ADC_FLAG_AWD1)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC analog watchdog 2. + * @rmtoll ISR AWD2 LL_ADC_IsActiveFlag_AWD2 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_AWD2(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_AWD2) == (LL_ADC_FLAG_AWD2)) ? 1UL : 0UL); +} + +/** + * @brief Get flag ADC analog watchdog 3. + * @rmtoll ISR AWD3 LL_ADC_IsActiveFlag_AWD3 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_AWD3(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->ISR, LL_ADC_FLAG_AWD3) == (LL_ADC_FLAG_AWD3)) ? 1UL : 0UL); +} + +/** + * @brief Clear flag ADC ready. + * @note On this STM32 series, flag LL_ADC_FLAG_ADRDY is raised when the ADC + * is enabled and when conversion clock is active. + * (not only core clock: this ADC has a dual clock domain) + * @rmtoll ISR ADRDY LL_ADC_ClearFlag_ADRDY + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_ADRDY(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_ADRDY); +} + +/** + * @brief Clear flag ADC group regular end of unitary conversion. + * @rmtoll ISR EOC LL_ADC_ClearFlag_EOC + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_EOC(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_EOC); +} + +/** + * @brief Clear flag ADC group regular end of sequence conversions. + * @rmtoll ISR EOS LL_ADC_ClearFlag_EOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_EOS(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_EOS); +} + +/** + * @brief Clear flag ADC group regular overrun. + * @rmtoll ISR OVR LL_ADC_ClearFlag_OVR + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_OVR(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_OVR); +} + +/** + * @brief Clear flag ADC group regular end of sampling phase. + * @rmtoll ISR EOSMP LL_ADC_ClearFlag_EOSMP + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_EOSMP(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_EOSMP); +} + +/** + * @brief Clear flag ADC group injected end of unitary conversion. + * @rmtoll ISR JEOC LL_ADC_ClearFlag_JEOC + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_JEOC(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_JEOC); +} + +/** + * @brief Clear flag ADC group injected end of sequence conversions. + * @rmtoll ISR JEOS LL_ADC_ClearFlag_JEOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_JEOS(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_JEOS); +} + +/** + * @brief Clear flag ADC group injected contexts queue overflow. + * @rmtoll ISR JQOVF LL_ADC_ClearFlag_JQOVF + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_JQOVF(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_JQOVF); +} + +/** + * @brief Clear flag ADC analog watchdog 1. + * @rmtoll ISR AWD1 LL_ADC_ClearFlag_AWD1 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_AWD1(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_AWD1); +} + +/** + * @brief Clear flag ADC analog watchdog 2. + * @rmtoll ISR AWD2 LL_ADC_ClearFlag_AWD2 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_AWD2(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_AWD2); +} + +/** + * @brief Clear flag ADC analog watchdog 3. + * @rmtoll ISR AWD3 LL_ADC_ClearFlag_AWD3 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_AWD3(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->ISR, LL_ADC_FLAG_AWD3); +} + +#if defined(ADC_MULTIMODE_SUPPORT) +/** + * @brief Get flag multimode ADC ready of the ADC master. + * @rmtoll CSR ADRDY_MST LL_ADC_IsActiveFlag_MST_ADRDY + * @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_ADRDY(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_ADRDY_MST) == (LL_ADC_FLAG_ADRDY_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC ready of the ADC slave. + * @rmtoll CSR ADRDY_SLV LL_ADC_IsActiveFlag_SLV_ADRDY + * @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_SLV_ADRDY(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_ADRDY_SLV) == (LL_ADC_FLAG_ADRDY_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular end of unitary conversion of the ADC master. + * @rmtoll CSR EOC_MST LL_ADC_IsActiveFlag_MST_EOC + * @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_EOC(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOC_SLV) == (LL_ADC_FLAG_EOC_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular end of unitary conversion of the ADC slave. + * @rmtoll CSR EOC_SLV LL_ADC_IsActiveFlag_SLV_EOC + * @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_SLV_EOC(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOC_SLV) == (LL_ADC_FLAG_EOC_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular end of sequence conversions of the ADC master. + * @rmtoll CSR EOS_MST LL_ADC_IsActiveFlag_MST_EOS + * @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_EOS(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOS_MST) == (LL_ADC_FLAG_EOS_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular end of sequence conversions of the ADC slave. + * @rmtoll CSR EOS_SLV LL_ADC_IsActiveFlag_SLV_EOS + * @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_SLV_EOS(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOS_SLV) == (LL_ADC_FLAG_EOS_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular overrun of the ADC master. + * @rmtoll CSR OVR_MST 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(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_OVR_MST) == (LL_ADC_FLAG_OVR_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular overrun of the ADC slave. + * @rmtoll CSR OVR_SLV LL_ADC_IsActiveFlag_SLV_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_SLV_OVR(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_OVR_SLV) == (LL_ADC_FLAG_OVR_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular end of sampling of the ADC master. + * @rmtoll CSR EOSMP_MST LL_ADC_IsActiveFlag_MST_EOSMP + * @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_EOSMP(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOSMP_MST) == (LL_ADC_FLAG_EOSMP_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group regular end of sampling of the ADC slave. + * @rmtoll CSR EOSMP_SLV LL_ADC_IsActiveFlag_SLV_EOSMP + * @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_SLV_EOSMP(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOSMP_SLV) == (LL_ADC_FLAG_EOSMP_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group injected end of unitary conversion of the ADC master. + * @rmtoll CSR JEOC_MST LL_ADC_IsActiveFlag_MST_JEOC + * @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_JEOC(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_JEOC_MST) == (LL_ADC_FLAG_JEOC_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group injected end of unitary conversion of the ADC slave. + * @rmtoll CSR JEOC_SLV LL_ADC_IsActiveFlag_SLV_JEOC + * @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_SLV_JEOC(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_JEOC_SLV) == (LL_ADC_FLAG_JEOC_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group injected end of sequence conversions of the ADC master. + * @rmtoll CSR JEOS_MST 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(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_JEOS_MST) == (LL_ADC_FLAG_JEOS_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group injected end of sequence conversions of the ADC slave. + * @rmtoll CSR JEOS_SLV LL_ADC_IsActiveFlag_SLV_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_SLV_JEOS(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_JEOS_SLV) == (LL_ADC_FLAG_JEOS_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group injected context queue overflow of the ADC master. + * @rmtoll CSR JQOVF_MST LL_ADC_IsActiveFlag_MST_JQOVF + * @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_JQOVF(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_JQOVF_MST) == (LL_ADC_FLAG_JQOVF_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC group injected context queue overflow of the ADC slave. + * @rmtoll CSR JQOVF_SLV LL_ADC_IsActiveFlag_SLV_JQOVF + * @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_SLV_JQOVF(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_JQOVF_SLV) == (LL_ADC_FLAG_JQOVF_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC analog watchdog 1 of the ADC master. + * @rmtoll CSR AWD1_MST 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(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD1_MST) == (LL_ADC_FLAG_AWD1_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode analog watchdog 1 of the ADC slave. + * @rmtoll CSR AWD1_SLV LL_ADC_IsActiveFlag_SLV_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_SLV_AWD1(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD1_SLV) == (LL_ADC_FLAG_AWD1_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC analog watchdog 2 of the ADC master. + * @rmtoll CSR AWD2_MST LL_ADC_IsActiveFlag_MST_AWD2 + * @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_AWD2(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD2_MST) == (LL_ADC_FLAG_AWD2_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC analog watchdog 2 of the ADC slave. + * @rmtoll CSR AWD2_SLV LL_ADC_IsActiveFlag_SLV_AWD2 + * @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_SLV_AWD2(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD2_SLV) == (LL_ADC_FLAG_AWD2_SLV)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC analog watchdog 3 of the ADC master. + * @rmtoll CSR AWD3_MST LL_ADC_IsActiveFlag_MST_AWD3 + * @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_AWD3(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD3_MST) == (LL_ADC_FLAG_AWD3_MST)) ? 1UL : 0UL); +} + +/** + * @brief Get flag multimode ADC analog watchdog 3 of the ADC slave. + * @rmtoll CSR AWD3_SLV LL_ADC_IsActiveFlag_SLV_AWD3 + * @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_SLV_AWD3(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + return ((READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD3_SLV) == (LL_ADC_FLAG_AWD3_SLV)) ? 1UL : 0UL); +} +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_IT_Management ADC IT management + * @{ + */ + +/** + * @brief Enable ADC ready. + * @rmtoll IER ADRDYIE LL_ADC_EnableIT_ADRDY + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_ADRDY(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_ADRDY); +} + +/** + * @brief Enable interruption ADC group regular end of unitary conversion. + * @rmtoll IER EOCIE LL_ADC_EnableIT_EOC + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_EOC(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_EOC); +} + +/** + * @brief Enable interruption ADC group regular end of sequence conversions. + * @rmtoll IER EOSIE LL_ADC_EnableIT_EOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_EOS(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_EOS); +} + +/** + * @brief Enable ADC group regular interruption overrun. + * @rmtoll IER OVRIE LL_ADC_EnableIT_OVR + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_OVR(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_OVR); +} + +/** + * @brief Enable interruption ADC group regular end of sampling. + * @rmtoll IER EOSMPIE LL_ADC_EnableIT_EOSMP + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_EOSMP(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_EOSMP); +} + +/** + * @brief Enable interruption ADC group injected end of unitary conversion. + * @rmtoll IER JEOCIE LL_ADC_EnableIT_JEOC + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_JEOC(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_JEOC); +} + +/** + * @brief Enable interruption ADC group injected end of sequence conversions. + * @rmtoll IER JEOSIE LL_ADC_EnableIT_JEOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_JEOS(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_JEOS); +} + +/** + * @brief Enable interruption ADC group injected context queue overflow. + * @rmtoll IER JQOVFIE LL_ADC_EnableIT_JQOVF + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_JQOVF(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_JQOVF); +} + +/** + * @brief Enable interruption ADC analog watchdog 1. + * @rmtoll IER AWD1IE LL_ADC_EnableIT_AWD1 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_AWD1(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_AWD1); +} + +/** + * @brief Enable interruption ADC analog watchdog 2. + * @rmtoll IER AWD2IE LL_ADC_EnableIT_AWD2 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_AWD2(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_AWD2); +} + +/** + * @brief Enable interruption ADC analog watchdog 3. + * @rmtoll IER AWD3IE LL_ADC_EnableIT_AWD3 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_AWD3(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->IER, LL_ADC_IT_AWD3); +} + +/** + * @brief Disable interruption ADC ready. + * @rmtoll IER ADRDYIE LL_ADC_DisableIT_ADRDY + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_ADRDY(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_ADRDY); +} + +/** + * @brief Disable interruption ADC group regular end of unitary conversion. + * @rmtoll IER EOCIE LL_ADC_DisableIT_EOC + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_EOC(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_EOC); +} + +/** + * @brief Disable interruption ADC group regular end of sequence conversions. + * @rmtoll IER EOSIE LL_ADC_DisableIT_EOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_EOS(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_EOS); +} + +/** + * @brief Disable interruption ADC group regular overrun. + * @rmtoll IER OVRIE LL_ADC_DisableIT_OVR + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_OVR(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_OVR); +} + +/** + * @brief Disable interruption ADC group regular end of sampling. + * @rmtoll IER EOSMPIE LL_ADC_DisableIT_EOSMP + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_EOSMP(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_EOSMP); +} + +/** + * @brief Disable interruption ADC group regular end of unitary conversion. + * @rmtoll IER JEOCIE LL_ADC_DisableIT_JEOC + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_JEOC(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_JEOC); +} + +/** + * @brief Disable interruption ADC group injected end of sequence conversions. + * @rmtoll IER JEOSIE LL_ADC_DisableIT_JEOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_JEOS(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_JEOS); +} + +/** + * @brief Disable interruption ADC group injected context queue overflow. + * @rmtoll IER JQOVFIE LL_ADC_DisableIT_JQOVF + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_JQOVF(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_JQOVF); +} + +/** + * @brief Disable interruption ADC analog watchdog 1. + * @rmtoll IER AWD1IE LL_ADC_DisableIT_AWD1 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_AWD1(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_AWD1); +} + +/** + * @brief Disable interruption ADC analog watchdog 2. + * @rmtoll IER AWD2IE LL_ADC_DisableIT_AWD2 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_AWD2(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_AWD2); +} + +/** + * @brief Disable interruption ADC analog watchdog 3. + * @rmtoll IER AWD3IE LL_ADC_DisableIT_AWD3 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_AWD3(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->IER, LL_ADC_IT_AWD3); +} + +/** + * @brief Get state of interruption ADC ready + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER ADRDYIE LL_ADC_IsEnabledIT_ADRDY + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_ADRDY(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_ADRDY) == (LL_ADC_IT_ADRDY)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group regular end of unitary conversion + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER EOCIE LL_ADC_IsEnabledIT_EOC + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_EOC(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_EOC) == (LL_ADC_IT_EOC)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group regular end of sequence conversions + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER EOSIE LL_ADC_IsEnabledIT_EOS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_EOS(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_EOS) == (LL_ADC_IT_EOS)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group regular overrun + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER OVRIE LL_ADC_IsEnabledIT_OVR + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_OVR(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_OVR) == (LL_ADC_IT_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group regular end of sampling + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER EOSMPIE LL_ADC_IsEnabledIT_EOSMP + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_EOSMP(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_EOSMP) == (LL_ADC_IT_EOSMP)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group injected end of unitary conversion + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER JEOCIE LL_ADC_IsEnabledIT_JEOC + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_JEOC(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_JEOC) == (LL_ADC_IT_JEOC)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group injected end of sequence conversions + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER JEOSIE LL_ADC_IsEnabledIT_JEOS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_JEOS(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_JEOS) == (LL_ADC_IT_JEOS)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC group injected context queue overflow interrupt state + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER JQOVFIE LL_ADC_IsEnabledIT_JQOVF + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_JQOVF(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_JQOVF) == (LL_ADC_IT_JQOVF)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption ADC analog watchdog 1 + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER AWD1IE LL_ADC_IsEnabledIT_AWD1 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_AWD1(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_AWD1) == (LL_ADC_IT_AWD1)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption Get ADC analog watchdog 2 + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER AWD2IE LL_ADC_IsEnabledIT_AWD2 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_AWD2(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_AWD2) == (LL_ADC_IT_AWD2)) ? 1UL : 0UL); +} + +/** + * @brief Get state of interruption Get ADC analog watchdog 3 + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll IER AWD3IE LL_ADC_IsEnabledIT_AWD3 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_AWD3(const ADC_TypeDef *ADCx) +{ + return ((READ_BIT(ADCx->IER, LL_ADC_IT_AWD3) == (LL_ADC_IT_AWD3)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#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(const ADC_Common_TypeDef *ADCxy_COMMON); +ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, const LL_ADC_CommonInitTypeDef *pADC_CommonInitStruct); +void LL_ADC_CommonStructInit(LL_ADC_CommonInitTypeDef *pADC_CommonInitStruct); + +/* De-initialization of ADC instance, ADC group regular and ADC group injected */ +/* (availability of ADC group injected depends on STM32 series) */ +ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx); + +/* Initialization of some features of ADC instance */ +ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, const LL_ADC_InitTypeDef *pADC_InitStruct); +void LL_ADC_StructInit(LL_ADC_InitTypeDef *pADC_InitStruct); + +/* Initialization of some features of ADC instance and ADC group regular */ +ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, const LL_ADC_REG_InitTypeDef *pADC_RegInitStruct); +void LL_ADC_REG_StructInit(LL_ADC_REG_InitTypeDef *pADC_RegInitStruct); + +/* Initialization of some features of ADC instance and ADC group injected */ +ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, const LL_ADC_INJ_InitTypeDef *pADC_InjInitStruct); +void LL_ADC_INJ_StructInit(LL_ADC_INJ_InitTypeDef *pADC_InjInitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ADC1 || ADC2 || ADC3 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_ADC_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_bus.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_bus.h new file mode 100644 index 0000000..55927f3 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_bus.h @@ -0,0 +1,1954 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_bus.h + * @author MCD Application Team + * @brief Header file of BUS LL module. + + @verbatim + ##### RCC Limitations ##### + ============================================================================== + [..] + A delay between an RCC peripheral clock enable and the effective peripheral + enabling should be taken into account in order to manage the peripheral read/write + from/to registers. + (+) This delay depends on the peripheral mapping. + (++) AHB & APB peripherals, 1 dummy read is necessary + + [..] + Workarounds: + (#) For AHB & APB peripherals, a dummy read to the peripheral register has been + inserted in each LL_{BUS}_GRP{x}_EnableClock() function. + + @endverbatim + ****************************************************************************** + * @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 STM32L4xx_LL_BUS_H +#define STM32L4xx_LL_BUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(RCC) + +/** @defgroup BUS_LL BUS + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup BUS_LL_Exported_Constants BUS Exported Constants + * @{ + */ + +/** @defgroup BUS_LL_EC_AHB1_GRP1_PERIPH AHB1 GRP1 PERIPH + * @{ + */ +#define LL_AHB1_GRP1_PERIPH_ALL 0xFFFFFFFFU +#define LL_AHB1_GRP1_PERIPH_DMA1 RCC_AHB1ENR_DMA1EN +#define LL_AHB1_GRP1_PERIPH_DMA2 RCC_AHB1ENR_DMA2EN +#if defined(DMAMUX1) +#define LL_AHB1_GRP1_PERIPH_DMAMUX1 RCC_AHB1ENR_DMAMUX1EN +#endif /* DMAMUX1 */ +#define LL_AHB1_GRP1_PERIPH_FLASH RCC_AHB1ENR_FLASHEN +#define LL_AHB1_GRP1_PERIPH_CRC RCC_AHB1ENR_CRCEN +#define LL_AHB1_GRP1_PERIPH_TSC RCC_AHB1ENR_TSCEN +#if defined(DMA2D) +#define LL_AHB1_GRP1_PERIPH_DMA2D RCC_AHB1ENR_DMA2DEN +#endif /* DMA2D */ +#if defined(GFXMMU) +#define LL_AHB1_GRP1_PERIPH_GFXMMU RCC_AHB1ENR_GFXMMUEN +#endif /* GFXMMU */ +#define LL_AHB1_GRP1_PERIPH_SRAM1 RCC_AHB1SMENR_SRAM1SMEN +/** + * @} + */ + +/** @defgroup BUS_LL_EC_AHB2_GRP1_PERIPH AHB2 GRP1 PERIPH + * @{ + */ +#define LL_AHB2_GRP1_PERIPH_ALL 0xFFFFFFFFU +#define LL_AHB2_GRP1_PERIPH_GPIOA RCC_AHB2ENR_GPIOAEN +#define LL_AHB2_GRP1_PERIPH_GPIOB RCC_AHB2ENR_GPIOBEN +#define LL_AHB2_GRP1_PERIPH_GPIOC RCC_AHB2ENR_GPIOCEN +#if defined(GPIOD) +#define LL_AHB2_GRP1_PERIPH_GPIOD RCC_AHB2ENR_GPIODEN +#endif /*GPIOD*/ +#if defined(GPIOE) +#define LL_AHB2_GRP1_PERIPH_GPIOE RCC_AHB2ENR_GPIOEEN +#endif /*GPIOE*/ +#if defined(GPIOF) +#define LL_AHB2_GRP1_PERIPH_GPIOF RCC_AHB2ENR_GPIOFEN +#endif /* GPIOF */ +#if defined(GPIOG) +#define LL_AHB2_GRP1_PERIPH_GPIOG RCC_AHB2ENR_GPIOGEN +#endif /* GPIOG */ +#define LL_AHB2_GRP1_PERIPH_GPIOH RCC_AHB2ENR_GPIOHEN +#if defined(GPIOI) +#define LL_AHB2_GRP1_PERIPH_GPIOI RCC_AHB2ENR_GPIOIEN +#endif /* GPIOI */ +#if defined(USB_OTG_FS) +#define LL_AHB2_GRP1_PERIPH_OTGFS RCC_AHB2ENR_OTGFSEN +#endif /* USB_OTG_FS */ +#define LL_AHB2_GRP1_PERIPH_ADC RCC_AHB2ENR_ADCEN +#if defined(DCMI) +#define LL_AHB2_GRP1_PERIPH_DCMI RCC_AHB2ENR_DCMIEN +#endif /* DCMI */ +#if defined(AES) +#define LL_AHB2_GRP1_PERIPH_AES RCC_AHB2ENR_AESEN +#endif /* AES */ +#if defined(HASH) +#define LL_AHB2_GRP1_PERIPH_HASH RCC_AHB2ENR_HASHEN +#endif /* HASH */ +#define LL_AHB2_GRP1_PERIPH_RNG RCC_AHB2ENR_RNGEN +#if defined(OCTOSPIM) +#define LL_AHB2_GRP1_PERIPH_OSPIM RCC_AHB2ENR_OSPIMEN +#endif /* OCTOSPIM */ +#if defined(PKA) +#define LL_AHB2_GRP1_PERIPH_PKA RCC_AHB2ENR_PKAEN +#endif /* PKA */ +#if defined(SDMMC1) && defined(RCC_AHB2ENR_SDMMC1EN) +#define LL_AHB2_GRP1_PERIPH_SDMMC1 RCC_AHB2ENR_SDMMC1EN +#endif /* SDMMC1 && RCC_AHB2ENR_SDMMC1EN */ +#define LL_AHB2_GRP1_PERIPH_SRAM2 RCC_AHB2SMENR_SRAM2SMEN +#if defined(SRAM3_BASE) +#define LL_AHB2_GRP1_PERIPH_SRAM3 RCC_AHB2SMENR_SRAM3SMEN +#endif /* SRAM3_BASE */ +/** + * @} + */ + +/** @defgroup BUS_LL_EC_AHB3_GRP1_PERIPH AHB3 GRP1 PERIPH + * @{ + */ +#define LL_AHB3_GRP1_PERIPH_ALL 0xFFFFFFFFU +#if defined(FMC_Bank1_R) +#define LL_AHB3_GRP1_PERIPH_FMC RCC_AHB3ENR_FMCEN +#endif /* FMC_Bank1_R */ +#if defined(QUADSPI) +#define LL_AHB3_GRP1_PERIPH_QSPI RCC_AHB3ENR_QSPIEN +#endif /* QUADSPI */ +#if defined(OCTOSPI1) +#define LL_AHB3_GRP1_PERIPH_OSPI1 RCC_AHB3ENR_OSPI1EN +#endif /* OCTOSPI1 */ +#if defined(OCTOSPI2) +#define LL_AHB3_GRP1_PERIPH_OSPI2 RCC_AHB3ENR_OSPI2EN +#endif /* OCTOSPI2 */ +/** + * @} + */ + +/** @defgroup BUS_LL_EC_APB1_GRP1_PERIPH APB1 GRP1 PERIPH + * @{ + */ +#define LL_APB1_GRP1_PERIPH_ALL 0xFFFFFFFFU +#define LL_APB1_GRP1_PERIPH_TIM2 RCC_APB1ENR1_TIM2EN +#if defined(TIM3) +#define LL_APB1_GRP1_PERIPH_TIM3 RCC_APB1ENR1_TIM3EN +#endif /* TIM3 */ +#if defined(TIM4) +#define LL_APB1_GRP1_PERIPH_TIM4 RCC_APB1ENR1_TIM4EN +#endif /* TIM4 */ +#if defined(TIM5) +#define LL_APB1_GRP1_PERIPH_TIM5 RCC_APB1ENR1_TIM5EN +#endif /* TIM5 */ +#define LL_APB1_GRP1_PERIPH_TIM6 RCC_APB1ENR1_TIM6EN +#define LL_APB1_GRP1_PERIPH_TIM7 RCC_APB1ENR1_TIM7EN +#if defined(LCD) +#define LL_APB1_GRP1_PERIPH_LCD RCC_APB1ENR1_LCDEN +#endif /* LCD */ +#if defined(RCC_APB1ENR1_RTCAPBEN) +#define LL_APB1_GRP1_PERIPH_RTCAPB RCC_APB1ENR1_RTCAPBEN +#endif /* RCC_APB1ENR1_RTCAPBEN */ +#define LL_APB1_GRP1_PERIPH_WWDG RCC_APB1ENR1_WWDGEN +#if defined(SPI2) +#define LL_APB1_GRP1_PERIPH_SPI2 RCC_APB1ENR1_SPI2EN +#endif /* SPI2 */ +#define LL_APB1_GRP1_PERIPH_SPI3 RCC_APB1ENR1_SPI3EN +#define LL_APB1_GRP1_PERIPH_USART2 RCC_APB1ENR1_USART2EN +#if defined(USART3) +#define LL_APB1_GRP1_PERIPH_USART3 RCC_APB1ENR1_USART3EN +#endif /* USART3 */ +#if defined(UART4) +#define LL_APB1_GRP1_PERIPH_UART4 RCC_APB1ENR1_UART4EN +#endif /* UART4 */ +#if defined(UART5) +#define LL_APB1_GRP1_PERIPH_UART5 RCC_APB1ENR1_UART5EN +#endif /* UART5 */ +#define LL_APB1_GRP1_PERIPH_I2C1 RCC_APB1ENR1_I2C1EN +#if defined(I2C2) +#define LL_APB1_GRP1_PERIPH_I2C2 RCC_APB1ENR1_I2C2EN +#endif /* I2C2 */ +#define LL_APB1_GRP1_PERIPH_I2C3 RCC_APB1ENR1_I2C3EN +#if defined(CRS) +#define LL_APB1_GRP1_PERIPH_CRS RCC_APB1ENR1_CRSEN +#endif /* CRS */ +#define LL_APB1_GRP1_PERIPH_CAN1 RCC_APB1ENR1_CAN1EN +#if defined(CAN2) +#define LL_APB1_GRP1_PERIPH_CAN2 RCC_APB1ENR1_CAN2EN +#endif /* CAN2 */ +#if defined(USB) +#define LL_APB1_GRP1_PERIPH_USB RCC_APB1ENR1_USBFSEN +#endif /* USB */ +#define LL_APB1_GRP1_PERIPH_PWR RCC_APB1ENR1_PWREN +#define LL_APB1_GRP1_PERIPH_DAC1 RCC_APB1ENR1_DAC1EN +#define LL_APB1_GRP1_PERIPH_OPAMP RCC_APB1ENR1_OPAMPEN +#define LL_APB1_GRP1_PERIPH_LPTIM1 RCC_APB1ENR1_LPTIM1EN +/** + * @} + */ + + +/** @defgroup BUS_LL_EC_APB1_GRP2_PERIPH APB1 GRP2 PERIPH + * @{ + */ +#define LL_APB1_GRP2_PERIPH_ALL 0xFFFFFFFFU +#define LL_APB1_GRP2_PERIPH_LPUART1 RCC_APB1ENR2_LPUART1EN +#if defined(I2C4) +#define LL_APB1_GRP2_PERIPH_I2C4 RCC_APB1ENR2_I2C4EN +#endif /* I2C4 */ +#if defined(SWPMI1) +#define LL_APB1_GRP2_PERIPH_SWPMI1 RCC_APB1ENR2_SWPMI1EN +#endif /* SWPMI1 */ +#define LL_APB1_GRP2_PERIPH_LPTIM2 RCC_APB1ENR2_LPTIM2EN +/** + * @} + */ + +/** @defgroup BUS_LL_EC_APB2_GRP1_PERIPH APB2 GRP1 PERIPH + * @{ + */ +#define LL_APB2_GRP1_PERIPH_ALL 0xFFFFFFFFU +#define LL_APB2_GRP1_PERIPH_SYSCFG RCC_APB2ENR_SYSCFGEN +#define LL_APB2_GRP1_PERIPH_FW RCC_APB2ENR_FWEN +#if defined(SDMMC1) && defined(RCC_APB2ENR_SDMMC1EN) +#define LL_APB2_GRP1_PERIPH_SDMMC1 RCC_APB2ENR_SDMMC1EN +#endif /* SDMMC1 && RCC_APB2ENR_SDMMC1EN */ +#define LL_APB2_GRP1_PERIPH_TIM1 RCC_APB2ENR_TIM1EN +#define LL_APB2_GRP1_PERIPH_SPI1 RCC_APB2ENR_SPI1EN +#if defined(TIM8) +#define LL_APB2_GRP1_PERIPH_TIM8 RCC_APB2ENR_TIM8EN +#endif /* TIM8 */ +#define LL_APB2_GRP1_PERIPH_USART1 RCC_APB2ENR_USART1EN +#define LL_APB2_GRP1_PERIPH_TIM15 RCC_APB2ENR_TIM15EN +#define LL_APB2_GRP1_PERIPH_TIM16 RCC_APB2ENR_TIM16EN +#if defined(TIM17) +#define LL_APB2_GRP1_PERIPH_TIM17 RCC_APB2ENR_TIM17EN +#endif /* TIM17 */ +#define LL_APB2_GRP1_PERIPH_SAI1 RCC_APB2ENR_SAI1EN +#if defined(SAI2) +#define LL_APB2_GRP1_PERIPH_SAI2 RCC_APB2ENR_SAI2EN +#endif /* SAI2 */ +#if defined(DFSDM1_Channel0) +#define LL_APB2_GRP1_PERIPH_DFSDM1 RCC_APB2ENR_DFSDM1EN +#endif /* DFSDM1_Channel0 */ +#if defined(LTDC) +#define LL_APB2_GRP1_PERIPH_LTDC RCC_APB2ENR_LTDCEN +#endif /* LTDC */ +#if defined(DSI) +#define LL_APB2_GRP1_PERIPH_DSI RCC_APB2ENR_DSIEN +#endif /* DSI */ +/** + * @} + */ + +/** Legacy definitions for compatibility purpose +@cond 0 +*/ +#if defined(DFSDM1_Channel0) +#define LL_APB2_GRP1_PERIPH_DFSDM LL_APB2_GRP1_PERIPH_DFSDM1 +#endif /* DFSDM1_Channel0 */ +/** +@endcond + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup BUS_LL_Exported_Functions BUS Exported Functions + * @{ + */ + +/** @defgroup BUS_LL_EF_AHB1 AHB1 + * @{ + */ + +/** + * @brief Enable AHB1 peripherals clock. + * @rmtoll AHB1ENR DMA1EN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR DMA2EN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR DMAMUX1EN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR FLASHEN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR CRCEN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR TSCEN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR DMA2DEN LL_AHB1_GRP1_EnableClock\n + * AHB1ENR GFXMMUEN LL_AHB1_GRP1_EnableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB1_GRP1_EnableClock(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->AHB1ENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHB1ENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Check if AHB1 peripheral clock is enabled or not + * @rmtoll AHB1ENR DMA1EN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR DMA2EN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR DMAMUX1EN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR FLASHEN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR CRCEN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR TSCEN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR DMA2DEN LL_AHB1_GRP1_IsEnabledClock\n + * AHB1ENR GFXMMUEN LL_AHB1_GRP1_IsEnabledClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval State of Periphs (1 or 0). +*/ +__STATIC_INLINE uint32_t LL_AHB1_GRP1_IsEnabledClock(uint32_t Periphs) +{ + return ((READ_BIT(RCC->AHB1ENR, Periphs) == Periphs) ? 1UL : 0UL); +} + +/** + * @brief Disable AHB1 peripherals clock. + * @rmtoll AHB1ENR DMA1EN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR DMA2EN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR DMAMUX1EN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR FLASHEN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR CRCEN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR TSCEN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR DMA2DEN LL_AHB1_GRP1_DisableClock\n + * AHB1ENR GFXMMUEN LL_AHB1_GRP1_DisableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB1_GRP1_DisableClock(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB1ENR, Periphs); +} + +/** + * @brief Force AHB1 peripherals reset. + * @rmtoll AHB1RSTR DMA1RST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR DMA2RST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR DMAMUX1RST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR FLASHRST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR CRCRST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR TSCRST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR DMA2DRST LL_AHB1_GRP1_ForceReset\n + * AHB1RSTR GFXMMURST LL_AHB1_GRP1_ForceReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_ALL + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB1_GRP1_ForceReset(uint32_t Periphs) +{ + SET_BIT(RCC->AHB1RSTR, Periphs); +} + +/** + * @brief Release AHB1 peripherals reset. + * @rmtoll AHB1RSTR DMA1RST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR DMA2RST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR DMAMUX1RST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR FLASHRST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR CRCRST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR TSCRST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR DMA2DRST LL_AHB1_GRP1_ReleaseReset\n + * AHB1RSTR GFXMMURST LL_AHB1_GRP1_ReleaseReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_ALL + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB1_GRP1_ReleaseReset(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB1RSTR, Periphs); +} + +/** + * @brief Enable AHB1 peripheral clocks in Sleep and Stop modes + * @rmtoll AHB1SMENR DMA1SMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR DMA2SMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR DMAMUX1SMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR FLASHSMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR SRAM1SMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR CRCSMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR TSCSMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR DMA2DSMEN LL_AHB1_GRP1_EnableClockStopSleep\n + * AHB1SMENR GFXMMUSMEN LL_AHB1_GRP1_EnableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_SRAM1 + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB1_GRP1_EnableClockStopSleep(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->AHB1SMENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHB1SMENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Disable AHB1 peripheral clocks in Sleep and Stop modes + * @rmtoll AHB1SMENR DMA1SMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR DMA2SMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR DMAMUX1SMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR FLASHSMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR SRAM1SMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR CRCSMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR TSCSMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR DMA2DSMEN LL_AHB1_GRP1_DisableClockStopSleep\n + * AHB1SMENR GFXMMUSMEN LL_AHB1_GRP1_DisableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA1 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2 + * @arg @ref LL_AHB1_GRP1_PERIPH_DMAMUX1 (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_FLASH + * @arg @ref LL_AHB1_GRP1_PERIPH_SRAM1 + * @arg @ref LL_AHB1_GRP1_PERIPH_CRC + * @arg @ref LL_AHB1_GRP1_PERIPH_TSC + * @arg @ref LL_AHB1_GRP1_PERIPH_DMA2D (*) + * @arg @ref LL_AHB1_GRP1_PERIPH_GFXMMU (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB1_GRP1_DisableClockStopSleep(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB1SMENR, Periphs); +} + +/** + * @} + */ + +/** @defgroup BUS_LL_EF_AHB2 AHB2 + * @{ + */ + +/** + * @brief Enable AHB2 peripherals clock. + * @rmtoll AHB2ENR GPIOAEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOBEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOCEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIODEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOEEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOFEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOGEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOHEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR GPIOIEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR OTGFSEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR ADCEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR DCMIEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR AESEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR HASHEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR RNGEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR OSPIMEN LL_AHB2_GRP1_EnableClock\n + * AHB2ENR SDMMC1EN LL_AHB2_GRP1_EnableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB2_GRP1_EnableClock(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->AHB2ENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHB2ENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Check if AHB2 peripheral clock is enabled or not + * @rmtoll AHB2ENR GPIOAEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOBEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOCEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIODEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOEEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOFEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOGEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOHEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR GPIOIEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR OTGFSEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR ADCEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR DCMIEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR AESEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR HASHEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR RNGEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR OSPIMEN LL_AHB2_GRP1_IsEnabledClock\n + * AHB2ENR SDMMC1EN LL_AHB2_GRP1_IsEnabledClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval State of Periphs (1 or 0). +*/ +__STATIC_INLINE uint32_t LL_AHB2_GRP1_IsEnabledClock(uint32_t Periphs) +{ + return ((READ_BIT(RCC->AHB2ENR, Periphs) == Periphs) ? 1UL : 0UL); +} + +/** + * @brief Disable AHB2 peripherals clock. + * @rmtoll AHB2ENR GPIOAEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOBEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOCEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIODEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOEEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOFEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOGEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOHEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR GPIOIEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR OTGFSEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR ADCEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR DCMIEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR AESEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR HASHEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR RNGEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR OSPIMEN LL_AHB2_GRP1_DisableClock\n + * AHB2ENR SDMMC1EN LL_AHB2_GRP1_DisableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB2_GRP1_DisableClock(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB2ENR, Periphs); +} + +/** + * @brief Force AHB2 peripherals reset. + * @rmtoll AHB2RSTR GPIOARST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOBRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOCRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIODRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOERST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOFRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOGRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOHRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR GPIOIRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR OTGFSRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR ADCRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR DCMIRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR AESRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR HASHRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR RNGRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR OSPIMRST LL_AHB2_GRP1_ForceReset\n + * AHB2RSTR SDMMC1RST LL_AHB2_GRP1_ForceReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_ALL + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB2_GRP1_ForceReset(uint32_t Periphs) +{ + SET_BIT(RCC->AHB2RSTR, Periphs); +} + +/** + * @brief Release AHB2 peripherals reset. + * @rmtoll AHB2RSTR GPIOARST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOBRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOCRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIODRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOERST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOFRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOGRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOHRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR GPIOIRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR OTGFSRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR ADCRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR DCMIRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR AESRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR HASHRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR RNGRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR OSPIMRST LL_AHB2_GRP1_ReleaseReset\n + * AHB2RSTR SDMMC1RST LL_AHB2_GRP1_ReleaseReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_ALL + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB2_GRP1_ReleaseReset(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB2RSTR, Periphs); +} + +/** + * @brief Enable AHB2 peripheral clocks in Sleep and Stop modes + * @rmtoll AHB2SMENR GPIOASMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOBSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOCSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIODSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOESMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOFSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOGSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOHSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR GPIOISMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR SRAM2SMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR SRAM3SMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR OTGFSSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR ADCSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR DCMISMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR AESSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR HASHSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR RNGSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR OSPIMSMEN LL_AHB2_GRP1_EnableClockStopSleep\n + * AHB2SMENR SDMMC1SMEN LL_AHB2_GRP1_EnableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SRAM2 + * @arg @ref LL_AHB2_GRP1_PERIPH_SRAM3 (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB2_GRP1_EnableClockStopSleep(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->AHB2SMENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHB2SMENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Disable AHB2 peripheral clocks in Sleep and Stop modes + * @rmtoll AHB2SMENR GPIOASMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOBSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOCSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIODSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOESMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOFSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOGSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOHSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR GPIOISMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR SRAM2SMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR SRAM3SMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR OTGFSSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR ADCSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR DCMISMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR AESSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR HASHSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR RNGSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR OSPIMSMEN LL_AHB2_GRP1_DisableClockStopSleep\n + * AHB2SMENR SDMMC1SMEN LL_AHB2_GRP1_DisableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOA + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOB + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOC + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOD (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOE (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOF (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOG (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOH + * @arg @ref LL_AHB2_GRP1_PERIPH_GPIOI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SRAM2 + * @arg @ref LL_AHB2_GRP1_PERIPH_SRAM3 (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_OTGFS (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_ADC + * @arg @ref LL_AHB2_GRP1_PERIPH_DCMI (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_AES (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_HASH (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_RNG + * @arg @ref LL_AHB2_GRP1_PERIPH_OSPIM (*) + * @arg @ref LL_AHB2_GRP1_PERIPH_SDMMC1 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB2_GRP1_DisableClockStopSleep(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB2SMENR, Periphs); +} + +/** + * @} + */ + +/** @defgroup BUS_LL_EF_AHB3 AHB3 + * @{ + */ + +/** + * @brief Enable AHB3 peripherals clock. + * @rmtoll AHB3ENR FMCEN LL_AHB3_GRP1_EnableClock\n + * AHB3ENR QSPIEN LL_AHB3_GRP1_EnableClock\n + * AHB3ENR OSPI1EN LL_AHB3_GRP1_EnableClock\n + * AHB3ENR OSPI2EN LL_AHB3_GRP1_EnableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB3_GRP1_EnableClock(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->AHB3ENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHB3ENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Check if AHB3 peripheral clock is enabled or not + * @rmtoll AHB3ENR FMCEN LL_AHB3_GRP1_IsEnabledClock\n + * AHB3ENR QSPIEN LL_AHB3_GRP1_IsEnabledClock\n + * AHB3ENR OSPI1EN LL_AHB3_GRP1_IsEnabledClock\n + * AHB3ENR OSPI2EN LL_AHB3_GRP1_IsEnabledClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval State of Periphs (1 or 0). +*/ +__STATIC_INLINE uint32_t LL_AHB3_GRP1_IsEnabledClock(uint32_t Periphs) +{ + return ((READ_BIT(RCC->AHB3ENR, Periphs) == Periphs) ? 1UL : 0UL); +} + +/** + * @brief Disable AHB3 peripherals clock. + * @rmtoll AHB3ENR FMCEN LL_AHB3_GRP1_DisableClock\n + * AHB3ENR QSPIEN LL_AHB3_GRP1_DisableClock\n + * AHB3ENR OSPI1EN LL_AHB3_GRP1_DisableClock\n + * AHB3ENR OSPI2EN LL_AHB3_GRP1_DisableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB3_GRP1_DisableClock(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB3ENR, Periphs); +} + +/** + * @brief Force AHB3 peripherals reset. + * @rmtoll AHB3RSTR FMCRST LL_AHB3_GRP1_ForceReset\n + * AHB3RSTR QSPIRST LL_AHB3_GRP1_ForceReset\n + * AHB3RSTR OSPI1RST LL_AHB3_GRP1_ForceReset\n + * AHB3RSTR OSPI2RST LL_AHB3_GRP1_ForceReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB3_GRP1_PERIPH_ALL + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB3_GRP1_ForceReset(uint32_t Periphs) +{ + SET_BIT(RCC->AHB3RSTR, Periphs); +} + +/** + * @brief Release AHB3 peripherals reset. + * @rmtoll AHB3RSTR FMCRST LL_AHB3_GRP1_ReleaseReset\n + * AHB3RSTR QSPIRST LL_AHB3_GRP1_ReleaseReset\n + * AHB3RSTR OSPI1RST LL_AHB3_GRP1_ReleaseReset\n + * AHB3RSTR OSPI2RST LL_AHB3_GRP1_ReleaseReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB2_GRP1_PERIPH_ALL + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB3_GRP1_ReleaseReset(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB3RSTR, Periphs); +} + +/** + * @brief Enable AHB3 peripheral clocks in Sleep and Stop modes + * @rmtoll AHB3SMENR FMCSMEN LL_AHB3_GRP1_EnableClockStopSleep\n + * AHB3SMENR QSPISMEN LL_AHB3_GRP1_EnableClockStopSleep\n + * AHB3SMENR OSPI1SMEN LL_AHB3_GRP1_EnableClockStopSleep\n + * AHB3SMENR OSPI2SMEN LL_AHB3_GRP1_EnableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB3_GRP1_EnableClockStopSleep(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->AHB3SMENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->AHB3SMENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Disable AHB3 peripheral clocks in Sleep and Stop modes + * @rmtoll AHB3SMENR FMCSMEN LL_AHB3_GRP1_DisableClockStopSleep\n + * AHB3SMENR QSPISMEN LL_AHB3_GRP1_DisableClockStopSleep\n + * AHB3SMENR OSPI1SMEN LL_AHB3_GRP1_DisableClockStopSleep\n + * AHB3SMENR OSPI2SMEN LL_AHB3_GRP1_DisableClockStopSleep\n + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_AHB3_GRP1_PERIPH_FMC (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_QSPI (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI1 (*) + * @arg @ref LL_AHB3_GRP1_PERIPH_OSPI2 (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_AHB3_GRP1_DisableClockStopSleep(uint32_t Periphs) +{ + CLEAR_BIT(RCC->AHB3SMENR, Periphs); +} + +/** + * @} + */ + +/** @defgroup BUS_LL_EF_APB1 APB1 + * @{ + */ + +/** + * @brief Enable APB1 peripherals clock. + * @rmtoll APB1ENR1 TIM2EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 TIM3EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 TIM4EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 TIM5EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 TIM6EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 TIM7EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 LCDEN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 RTCAPBEN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 WWDGEN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 SPI2EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 SPI3EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 USART2EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 USART3EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 UART4EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 UART5EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 I2C1EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 I2C2EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 I2C3EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 CRSEN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 CAN1EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 USBFSEN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 CAN2EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 PWREN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 DAC1EN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 OPAMPEN LL_APB1_GRP1_EnableClock\n + * APB1ENR1 LPTIM1EN LL_APB1_GRP1_EnableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_RTCAPB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_WWDG + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP1_EnableClock(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->APB1ENR1, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB1ENR1, Periphs); + (void)tmpreg; +} + +/** + * @brief Enable APB1 peripherals clock. + * @rmtoll APB1ENR2 LPUART1EN LL_APB1_GRP2_EnableClock\n + * APB1ENR2 I2C4EN LL_APB1_GRP2_EnableClock\n + * APB1ENR2 SWPMI1EN LL_APB1_GRP2_EnableClock\n + * APB1ENR2 LPTIM2EN LL_APB1_GRP2_EnableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP2_EnableClock(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->APB1ENR2, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB1ENR2, Periphs); + (void)tmpreg; +} + +/** + * @brief Check if APB1 peripheral clock is enabled or not + * @rmtoll APB1ENR1 TIM2EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 TIM3EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 TIM4EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 TIM5EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 TIM6EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 TIM7EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 LCDEN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 RTCAPBEN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 WWDGEN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 SPI2EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 SPI3EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 USART2EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 USART3EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 UART4EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 UART5EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 I2C1EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 I2C2EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 I2C3EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 CRSEN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 CAN1EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 USBFSEN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 CAN2EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 PWREN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 DAC1EN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 OPAMPEN LL_APB1_GRP1_IsEnabledClock\n + * APB1ENR1 LPTIM1EN LL_APB1_GRP1_IsEnabledClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_RTCAPB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_WWDG + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval State of Periphs (1 or 0). +*/ +__STATIC_INLINE uint32_t LL_APB1_GRP1_IsEnabledClock(uint32_t Periphs) +{ + return ((READ_BIT(RCC->APB1ENR1, Periphs) == Periphs) ? 1UL : 0UL); +} + +/** + * @brief Check if APB1 peripheral clock is enabled or not + * @rmtoll APB1ENR2 LPUART1EN LL_APB1_GRP2_IsEnabledClock\n + * APB1ENR2 I2C4EN LL_APB1_GRP2_IsEnabledClock\n + * APB1ENR2 SWPMI1EN LL_APB1_GRP2_IsEnabledClock\n + * APB1ENR2 LPTIM2EN LL_APB1_GRP2_IsEnabledClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval State of Periphs (1 or 0). +*/ +__STATIC_INLINE uint32_t LL_APB1_GRP2_IsEnabledClock(uint32_t Periphs) +{ + return ((READ_BIT(RCC->APB1ENR2, Periphs) == Periphs) ? 1UL : 0UL); +} + +/** + * @brief Disable APB1 peripherals clock. + * @rmtoll APB1ENR1 TIM2EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 TIM3EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 TIM4EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 TIM5EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 TIM6EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 TIM7EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 LCDEN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 RTCAPBEN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 WWDGEN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 SPI2EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 SPI3EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 USART2EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 USART3EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 UART4EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 UART5EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 I2C1EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 I2C2EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 I2C3EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 CRSEN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 CAN1EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 USBFSEN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 CAN2EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 PWREN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 DAC1EN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 OPAMPEN LL_APB1_GRP1_DisableClock\n + * APB1ENR1 LPTIM1EN LL_APB1_GRP1_DisableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_RTCAPB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_WWDG + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP1_DisableClock(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB1ENR1, Periphs); +} + +/** + * @brief Disable APB1 peripherals clock. + * @rmtoll APB1ENR2 LPUART1EN LL_APB1_GRP2_DisableClock\n + * APB1ENR2 I2C4EN LL_APB1_GRP2_DisableClock\n + * APB1ENR2 SWPMI1EN LL_APB1_GRP2_DisableClock\n + * APB1ENR2 LPTIM2EN LL_APB1_GRP2_DisableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP2_DisableClock(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB1ENR2, Periphs); +} + +/** + * @brief Force APB1 peripherals reset. + * @rmtoll APB1RSTR1 TIM2RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 TIM3RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 TIM4RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 TIM5RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 TIM6RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 TIM7RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 LCDRST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 SPI2RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 SPI3RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 USART2RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 USART3RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 UART4RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 UART5RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 I2C1RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 I2C2RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 I2C3RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 CRSRST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 CAN1RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 USBFSRST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 CAN2RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 PWRRST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 DAC1RST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 OPAMPRST LL_APB1_GRP1_ForceReset\n + * APB1RSTR1 LPTIM1RST LL_APB1_GRP1_ForceReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_ALL + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP1_ForceReset(uint32_t Periphs) +{ + SET_BIT(RCC->APB1RSTR1, Periphs); +} + +/** + * @brief Force APB1 peripherals reset. + * @rmtoll APB1RSTR2 LPUART1RST LL_APB1_GRP2_ForceReset\n + * APB1RSTR2 I2C4RST LL_APB1_GRP2_ForceReset\n + * APB1RSTR2 SWPMI1RST LL_APB1_GRP2_ForceReset\n + * APB1RSTR2 LPTIM2RST LL_APB1_GRP2_ForceReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_ALL + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP2_ForceReset(uint32_t Periphs) +{ + SET_BIT(RCC->APB1RSTR2, Periphs); +} + +/** + * @brief Release APB1 peripherals reset. + * @rmtoll APB1RSTR1 TIM2RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 TIM3RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 TIM4RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 TIM5RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 TIM6RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 TIM7RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 LCDRST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 SPI2RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 SPI3RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 USART2RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 USART3RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 UART4RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 UART5RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 I2C1RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 I2C2RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 I2C3RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 CRSRST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 CAN1RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 USBFSRST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 CAN2RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 PWRRST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 DAC1RST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 OPAMPRST LL_APB1_GRP1_ReleaseReset\n + * APB1RSTR1 LPTIM1RST LL_APB1_GRP1_ReleaseReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_ALL + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP1_ReleaseReset(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB1RSTR1, Periphs); +} + +/** + * @brief Release APB1 peripherals reset. + * @rmtoll APB1RSTR2 LPUART1RST LL_APB1_GRP2_ReleaseReset\n + * APB1RSTR2 I2C4RST LL_APB1_GRP2_ReleaseReset\n + * APB1RSTR2 SWPMI1RST LL_APB1_GRP2_ReleaseReset\n + * APB1RSTR2 LPTIM2RST LL_APB1_GRP2_ReleaseReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_ALL + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP2_ReleaseReset(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB1RSTR2, Periphs); +} + +/** + * @brief Enable APB1 peripheral clocks in Sleep and Stop modes + * @rmtoll APB1SMENR1 TIM2SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 TIM3SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 TIM4SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 TIM5SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 TIM6SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 TIM7SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 LCDSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 RTCAPBSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 WWDGSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 SPI2SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 SPI3SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 USART2SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 USART3SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 UART4SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 UART5SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 I2C1SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 I2C2SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 I2C3SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 CRSSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 CAN1SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 USBFSSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 CAN2SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 PWRSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 DAC1SMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 OPAMPSMEN LL_APB1_GRP1_EnableClockStopSleep\n + * APB1SMENR1 LPTIM1SMEN LL_APB1_GRP1_EnableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_RTCAPB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_WWDG + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP1_EnableClockStopSleep(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->APB1SMENR1, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB1SMENR1, Periphs); + (void)tmpreg; +} + +/** + * @brief Enable APB1 peripheral clocks in Sleep and Stop modes + * @rmtoll APB1SMENR2 LPUART1SMEN LL_APB1_GRP2_EnableClockStopSleep\n + * APB1SMENR2 I2C4SMEN LL_APB1_GRP2_EnableClockStopSleep\n + * APB1SMENR2 SWPMI1SMEN LL_APB1_GRP2_EnableClockStopSleep\n + * APB1SMENR2 LPTIM2SMEN LL_APB1_GRP2_EnableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP2_EnableClockStopSleep(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->APB1SMENR2, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB1SMENR2, Periphs); + (void)tmpreg; +} + +/** + * @brief Disable APB1 peripheral clocks in Sleep and Stop modes + * @rmtoll APB1SMENR1 TIM2SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 TIM3SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 TIM4SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 TIM5SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 TIM6SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 TIM7SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 LCDSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 RTCAPBSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 WWDGSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 SPI2SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 SPI3SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 USART2SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 USART3SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 UART4SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 UART5SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 I2C1SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 I2C2SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 I2C3SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 CRSSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 CAN1SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 USBFSSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 CAN2SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 PWRSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 DAC1SMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 OPAMPSMEN LL_APB1_GRP1_DisableClockStopSleep\n + * APB1SMENR1 LPTIM1SMEN LL_APB1_GRP1_DisableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP1_PERIPH_TIM2 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_TIM6 + * @arg @ref LL_APB1_GRP1_PERIPH_TIM7 + * @arg @ref LL_APB1_GRP1_PERIPH_LCD (*) + * @arg @ref LL_APB1_GRP1_PERIPH_RTCAPB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_WWDG + * @arg @ref LL_APB1_GRP1_PERIPH_SPI2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_SPI3 + * @arg @ref LL_APB1_GRP1_PERIPH_USART2 + * @arg @ref LL_APB1_GRP1_PERIPH_USART3 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART4 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_UART5 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C1 + * @arg @ref LL_APB1_GRP1_PERIPH_I2C2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_I2C3 + * @arg @ref LL_APB1_GRP1_PERIPH_CRS (*) + * @arg @ref LL_APB1_GRP1_PERIPH_CAN1 + * @arg @ref LL_APB1_GRP1_PERIPH_CAN2 (*) + * @arg @ref LL_APB1_GRP1_PERIPH_USB (*) + * @arg @ref LL_APB1_GRP1_PERIPH_PWR + * @arg @ref LL_APB1_GRP1_PERIPH_DAC1 + * @arg @ref LL_APB1_GRP1_PERIPH_OPAMP + * @arg @ref LL_APB1_GRP1_PERIPH_LPTIM1 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP1_DisableClockStopSleep(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB1SMENR1, Periphs); +} + +/** + * @brief Disable APB1 peripheral clocks in Sleep and Stop modes + * @rmtoll APB1SMENR2 LPUART1SMEN LL_APB1_GRP2_DisableClockStopSleep\n + * APB1SMENR2 I2C4SMEN LL_APB1_GRP2_DisableClockStopSleep\n + * APB1SMENR2 SWPMI1SMEN LL_APB1_GRP2_DisableClockStopSleep\n + * APB1SMENR2 LPTIM2SMEN LL_APB1_GRP2_DisableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB1_GRP2_PERIPH_LPUART1 + * @arg @ref LL_APB1_GRP2_PERIPH_I2C4 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_SWPMI1 (*) + * @arg @ref LL_APB1_GRP2_PERIPH_LPTIM2 + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB1_GRP2_DisableClockStopSleep(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB1SMENR2, Periphs); +} + +/** + * @} + */ + +/** @defgroup BUS_LL_EF_APB2 APB2 + * @{ + */ + +/** + * @brief Enable APB2 peripherals clock. + * @rmtoll APB2ENR SYSCFGEN LL_APB2_GRP1_EnableClock\n + * APB2ENR FWEN LL_APB2_GRP1_EnableClock\n + * APB2ENR SDMMC1EN LL_APB2_GRP1_EnableClock\n + * APB2ENR TIM1EN LL_APB2_GRP1_EnableClock\n + * APB2ENR SPI1EN LL_APB2_GRP1_EnableClock\n + * APB2ENR TIM8EN LL_APB2_GRP1_EnableClock\n + * APB2ENR USART1EN LL_APB2_GRP1_EnableClock\n + * APB2ENR TIM15EN LL_APB2_GRP1_EnableClock\n + * APB2ENR TIM16EN LL_APB2_GRP1_EnableClock\n + * APB2ENR TIM17EN LL_APB2_GRP1_EnableClock\n + * APB2ENR SAI1EN LL_APB2_GRP1_EnableClock\n + * APB2ENR SAI2EN LL_APB2_GRP1_EnableClock\n + * APB2ENR DFSDM1EN LL_APB2_GRP1_EnableClock\n + * APB2ENR LTDCEN LL_APB2_GRP1_EnableClock\n + * APB2ENR DSIEN LL_APB2_GRP1_EnableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_FW + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB2_GRP1_EnableClock(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->APB2ENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB2ENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Check if APB2 peripheral clock is enabled or not + * @rmtoll APB2ENR SYSCFGEN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR FWEN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR SDMMC1EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR TIM1EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR SPI1EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR TIM8EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR USART1EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR TIM15EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR TIM16EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR TIM17EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR SAI1EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR SAI2EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR DFSDM1EN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR LTDCEN LL_APB2_GRP1_IsEnabledClock\n + * APB2ENR DSIEN LL_APB2_GRP1_IsEnabledClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_FW + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval State of Periphs (1 or 0). +*/ +__STATIC_INLINE uint32_t LL_APB2_GRP1_IsEnabledClock(uint32_t Periphs) +{ + return ((READ_BIT(RCC->APB2ENR, Periphs) == Periphs) ? 1UL : 0UL); +} + +/** + * @brief Disable APB2 peripherals clock. + * @rmtoll APB2ENR SYSCFGEN LL_APB2_GRP1_DisableClock\n + * APB2ENR SDMMC1EN LL_APB2_GRP1_DisableClock\n + * APB2ENR TIM1EN LL_APB2_GRP1_DisableClock\n + * APB2ENR SPI1EN LL_APB2_GRP1_DisableClock\n + * APB2ENR TIM8EN LL_APB2_GRP1_DisableClock\n + * APB2ENR USART1EN LL_APB2_GRP1_DisableClock\n + * APB2ENR TIM15EN LL_APB2_GRP1_DisableClock\n + * APB2ENR TIM16EN LL_APB2_GRP1_DisableClock\n + * APB2ENR TIM17EN LL_APB2_GRP1_DisableClock\n + * APB2ENR SAI1EN LL_APB2_GRP1_DisableClock\n + * APB2ENR SAI2EN LL_APB2_GRP1_DisableClock\n + * APB2ENR DFSDM1EN LL_APB2_GRP1_DisableClock\n + * APB2ENR LTDCEN LL_APB2_GRP1_DisableClock\n + * APB2ENR DSIEN LL_APB2_GRP1_DisableClock + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB2_GRP1_DisableClock(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB2ENR, Periphs); +} + +/** + * @brief Force APB2 peripherals reset. + * @rmtoll APB2RSTR SYSCFGRST LL_APB2_GRP1_ForceReset\n + * APB2RSTR SDMMC1RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR TIM1RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR SPI1RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR TIM8RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR USART1RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR TIM15RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR TIM16RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR TIM17RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR SAI1RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR SAI2RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR DFSDM1RST LL_APB2_GRP1_ForceReset\n + * APB2RSTR LTDCRST LL_APB2_GRP1_ForceReset\n + * APB2RSTR DSIRST LL_APB2_GRP1_ForceReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_ALL + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB2_GRP1_ForceReset(uint32_t Periphs) +{ + SET_BIT(RCC->APB2RSTR, Periphs); +} + +/** + * @brief Release APB2 peripherals reset. + * @rmtoll APB2RSTR SYSCFGRST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR SDMMC1RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR TIM1RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR SPI1RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR TIM8RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR USART1RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR TIM15RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR TIM16RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR TIM17RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR SAI1RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR SAI2RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR DFSDM1RST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR LTDCRST LL_APB2_GRP1_ReleaseReset\n + * APB2RSTR DSIRST LL_APB2_GRP1_ReleaseReset + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_ALL + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB2_GRP1_ReleaseReset(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB2RSTR, Periphs); +} + +/** + * @brief Enable APB2 peripheral clocks in Sleep and Stop modes + * @rmtoll APB2SMENR SYSCFGSMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR SDMMC1SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR TIM1SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR SPI1SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR TIM8SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR USART1SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR TIM15SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR TIM16SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR TIM17SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR SAI1SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR SAI2SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR DFSDM1SMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR LTDCSMEN LL_APB2_GRP1_EnableClockStopSleep\n + * APB2SMENR DSISMEN LL_APB2_GRP1_EnableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB2_GRP1_EnableClockStopSleep(uint32_t Periphs) +{ + __IO uint32_t tmpreg; + SET_BIT(RCC->APB2SMENR, Periphs); + /* Delay after an RCC peripheral clock enabling */ + tmpreg = READ_BIT(RCC->APB2SMENR, Periphs); + (void)tmpreg; +} + +/** + * @brief Disable APB2 peripheral clocks in Sleep and Stop modes + * @rmtoll APB2SMENR SYSCFGSMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR SDMMC1SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR TIM1SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR SPI1SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR TIM8SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR USART1SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR TIM15SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR TIM16SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR TIM17SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR SAI1SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR SAI2SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR DFSDM1SMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR LTDCSMEN LL_APB2_GRP1_DisableClockStopSleep\n + * APB2SMENR DSISMEN LL_APB2_GRP1_DisableClockStopSleep + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_APB2_GRP1_PERIPH_SYSCFG + * @arg @ref LL_APB2_GRP1_PERIPH_SDMMC1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_TIM1 + * @arg @ref LL_APB2_GRP1_PERIPH_SPI1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM8 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_USART1 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM15 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM16 + * @arg @ref LL_APB2_GRP1_PERIPH_TIM17 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_SAI1 + * @arg @ref LL_APB2_GRP1_PERIPH_SAI2 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DFSDM1 (*) + * @arg @ref LL_APB2_GRP1_PERIPH_LTDC (*) + * @arg @ref LL_APB2_GRP1_PERIPH_DSI (*) + * + * (*) value not defined in all devices. + * @retval None +*/ +__STATIC_INLINE void LL_APB2_GRP1_DisableClockStopSleep(uint32_t Periphs) +{ + CLEAR_BIT(RCC->APB2SMENR, Periphs); +} + +/** + * @} + */ + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(RCC) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_BUS_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_cortex.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_cortex.h new file mode 100644 index 0000000..4ad94d6 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_cortex.h @@ -0,0 +1,637 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_cortex.h + * @author MCD Application Team + * @brief Header file of CORTEX LL module. + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The LL CORTEX driver contains a set of generic APIs that can be + used by user: + (+) SYSTICK configuration used by @ref LL_mDelay and @ref LL_Init1msTick + functions + (+) Low power mode configuration (SCB register of Cortex-MCU) + (+) MPU API to configure and enable regions + (+) API to access to MCU info (CPUID register) + (+) API to enable fault handler (SHCSR accesses) + + @endverbatim + ****************************************************************************** + * @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 STM32L4xx_LL_CORTEX_H +#define STM32L4xx_LL_CORTEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +/** @defgroup CORTEX_LL CORTEX + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CORTEX_LL_Exported_Constants CORTEX Exported Constants + * @{ + */ + +/** @defgroup CORTEX_LL_EC_CLKSOURCE_HCLK SYSTICK Clock Source + * @{ + */ +#define LL_SYSTICK_CLKSOURCE_HCLK_DIV8 0x00000000U /*!< AHB clock divided by 8 selected as SysTick clock source.*/ +#define LL_SYSTICK_CLKSOURCE_HCLK SysTick_CTRL_CLKSOURCE_Msk /*!< AHB clock selected as SysTick clock source. */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_FAULT Handler Fault type + * @{ + */ +#define LL_HANDLER_FAULT_USG SCB_SHCSR_USGFAULTENA_Msk /*!< Usage fault */ +#define LL_HANDLER_FAULT_BUS SCB_SHCSR_BUSFAULTENA_Msk /*!< Bus fault */ +#define LL_HANDLER_FAULT_MEM SCB_SHCSR_MEMFAULTENA_Msk /*!< Memory management fault */ +/** + * @} + */ + +#if __MPU_PRESENT + +/** @defgroup CORTEX_LL_EC_CTRL_HFNMI_PRIVDEF MPU Control + * @{ + */ +#define LL_MPU_CTRL_HFNMI_PRIVDEF_NONE 0x00000000U /*!< Disable NMI and privileged SW access */ +#define LL_MPU_CTRL_HARDFAULT_NMI MPU_CTRL_HFNMIENA_Msk /*!< Enables the operation of MPU during hard fault, NMI, and FAULTMASK handlers */ +#define LL_MPU_CTRL_PRIVILEGED_DEFAULT MPU_CTRL_PRIVDEFENA_Msk /*!< Enable privileged software access to default memory map */ +#define LL_MPU_CTRL_HFNMI_PRIVDEF (MPU_CTRL_HFNMIENA_Msk | MPU_CTRL_PRIVDEFENA_Msk) /*!< Enable NMI and privileged SW access */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_REGION MPU Region Number + * @{ + */ +#define LL_MPU_REGION_NUMBER0 0x00U /*!< REGION Number 0 */ +#define LL_MPU_REGION_NUMBER1 0x01U /*!< REGION Number 1 */ +#define LL_MPU_REGION_NUMBER2 0x02U /*!< REGION Number 2 */ +#define LL_MPU_REGION_NUMBER3 0x03U /*!< REGION Number 3 */ +#define LL_MPU_REGION_NUMBER4 0x04U /*!< REGION Number 4 */ +#define LL_MPU_REGION_NUMBER5 0x05U /*!< REGION Number 5 */ +#define LL_MPU_REGION_NUMBER6 0x06U /*!< REGION Number 6 */ +#define LL_MPU_REGION_NUMBER7 0x07U /*!< REGION Number 7 */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_REGION_SIZE MPU Region Size + * @{ + */ +#define LL_MPU_REGION_SIZE_32B (0x04U << MPU_RASR_SIZE_Pos) /*!< 32B Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_64B (0x05U << MPU_RASR_SIZE_Pos) /*!< 64B Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_128B (0x06U << MPU_RASR_SIZE_Pos) /*!< 128B Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_256B (0x07U << MPU_RASR_SIZE_Pos) /*!< 256B Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_512B (0x08U << MPU_RASR_SIZE_Pos) /*!< 512B Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_1KB (0x09U << MPU_RASR_SIZE_Pos) /*!< 1KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_2KB (0x0AU << MPU_RASR_SIZE_Pos) /*!< 2KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_4KB (0x0BU << MPU_RASR_SIZE_Pos) /*!< 4KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_8KB (0x0CU << MPU_RASR_SIZE_Pos) /*!< 8KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_16KB (0x0DU << MPU_RASR_SIZE_Pos) /*!< 16KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_32KB (0x0EU << MPU_RASR_SIZE_Pos) /*!< 32KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_64KB (0x0FU << MPU_RASR_SIZE_Pos) /*!< 64KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_128KB (0x10U << MPU_RASR_SIZE_Pos) /*!< 128KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_256KB (0x11U << MPU_RASR_SIZE_Pos) /*!< 256KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_512KB (0x12U << MPU_RASR_SIZE_Pos) /*!< 512KB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_1MB (0x13U << MPU_RASR_SIZE_Pos) /*!< 1MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_2MB (0x14U << MPU_RASR_SIZE_Pos) /*!< 2MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_4MB (0x15U << MPU_RASR_SIZE_Pos) /*!< 4MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_8MB (0x16U << MPU_RASR_SIZE_Pos) /*!< 8MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_16MB (0x17U << MPU_RASR_SIZE_Pos) /*!< 16MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_32MB (0x18U << MPU_RASR_SIZE_Pos) /*!< 32MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_64MB (0x19U << MPU_RASR_SIZE_Pos) /*!< 64MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_128MB (0x1AU << MPU_RASR_SIZE_Pos) /*!< 128MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_256MB (0x1BU << MPU_RASR_SIZE_Pos) /*!< 256MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_512MB (0x1CU << MPU_RASR_SIZE_Pos) /*!< 512MB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_1GB (0x1DU << MPU_RASR_SIZE_Pos) /*!< 1GB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_2GB (0x1EU << MPU_RASR_SIZE_Pos) /*!< 2GB Size of the MPU protection region */ +#define LL_MPU_REGION_SIZE_4GB (0x1FU << MPU_RASR_SIZE_Pos) /*!< 4GB Size of the MPU protection region */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_REGION_PRIVILEDGES MPU Region Privileges + * @{ + */ +#define LL_MPU_REGION_NO_ACCESS (0x00U << MPU_RASR_AP_Pos) /*!< No access*/ +#define LL_MPU_REGION_PRIV_RW (0x01U << MPU_RASR_AP_Pos) /*!< RW privileged (privileged access only)*/ +#define LL_MPU_REGION_PRIV_RW_URO (0x02U << MPU_RASR_AP_Pos) /*!< RW privileged - RO user (Write in a user program generates a fault) */ +#define LL_MPU_REGION_FULL_ACCESS (0x03U << MPU_RASR_AP_Pos) /*!< RW privileged & user (Full access) */ +#define LL_MPU_REGION_PRIV_RO (0x05U << MPU_RASR_AP_Pos) /*!< RO privileged (privileged read only)*/ +#define LL_MPU_REGION_PRIV_RO_URO (0x06U << MPU_RASR_AP_Pos) /*!< RO privileged & user (read only) */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_TEX MPU TEX Level + * @{ + */ +#define LL_MPU_TEX_LEVEL0 (0x00U << MPU_RASR_TEX_Pos) /*!< b000 for TEX bits */ +#define LL_MPU_TEX_LEVEL1 (0x01U << MPU_RASR_TEX_Pos) /*!< b001 for TEX bits */ +#define LL_MPU_TEX_LEVEL2 (0x02U << MPU_RASR_TEX_Pos) /*!< b010 for TEX bits */ +#define LL_MPU_TEX_LEVEL4 (0x04U << MPU_RASR_TEX_Pos) /*!< b100 for TEX bits */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_INSTRUCTION_ACCESS MPU Instruction Access + * @{ + */ +#define LL_MPU_INSTRUCTION_ACCESS_ENABLE 0x00U /*!< Instruction fetches enabled */ +#define LL_MPU_INSTRUCTION_ACCESS_DISABLE MPU_RASR_XN_Msk /*!< Instruction fetches disabled*/ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_SHAREABLE_ACCESS MPU Shareable Access + * @{ + */ +#define LL_MPU_ACCESS_SHAREABLE MPU_RASR_S_Msk /*!< Shareable memory attribute */ +#define LL_MPU_ACCESS_NOT_SHAREABLE 0x00U /*!< Not Shareable memory attribute */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_CACHEABLE_ACCESS MPU Cacheable Access + * @{ + */ +#define LL_MPU_ACCESS_CACHEABLE MPU_RASR_C_Msk /*!< Cacheable memory attribute */ +#define LL_MPU_ACCESS_NOT_CACHEABLE 0x00U /*!< Not Cacheable memory attribute */ +/** + * @} + */ + +/** @defgroup CORTEX_LL_EC_BUFFERABLE_ACCESS MPU Bufferable Access + * @{ + */ +#define LL_MPU_ACCESS_BUFFERABLE MPU_RASR_B_Msk /*!< Bufferable memory attribute */ +#define LL_MPU_ACCESS_NOT_BUFFERABLE 0x00U /*!< Not Bufferable memory attribute */ +/** + * @} + */ +#endif /* __MPU_PRESENT */ +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CORTEX_LL_Exported_Functions CORTEX Exported Functions + * @{ + */ + +/** @defgroup CORTEX_LL_EF_SYSTICK SYSTICK + * @{ + */ + +/** + * @brief This function checks if the Systick counter flag is active or not. + * @note It can be used in timeout function on application side. + * @rmtoll STK_CTRL COUNTFLAG LL_SYSTICK_IsActiveCounterFlag + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSTICK_IsActiveCounterFlag(void) +{ + return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == (SysTick_CTRL_COUNTFLAG_Msk)); +} + +/** + * @brief Configures the SysTick clock source + * @rmtoll STK_CTRL CLKSOURCE LL_SYSTICK_SetClkSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_SYSTICK_CLKSOURCE_HCLK_DIV8 + * @arg @ref LL_SYSTICK_CLKSOURCE_HCLK + * @retval None + */ +__STATIC_INLINE void LL_SYSTICK_SetClkSource(uint32_t Source) +{ + if (Source == LL_SYSTICK_CLKSOURCE_HCLK) + { + SET_BIT(SysTick->CTRL, LL_SYSTICK_CLKSOURCE_HCLK); + } + else + { + CLEAR_BIT(SysTick->CTRL, LL_SYSTICK_CLKSOURCE_HCLK); + } +} + +/** + * @brief Get the SysTick clock source + * @rmtoll STK_CTRL CLKSOURCE LL_SYSTICK_GetClkSource + * @retval Returned value can be one of the following values: + * @arg @ref LL_SYSTICK_CLKSOURCE_HCLK_DIV8 + * @arg @ref LL_SYSTICK_CLKSOURCE_HCLK + */ +__STATIC_INLINE uint32_t LL_SYSTICK_GetClkSource(void) +{ + return READ_BIT(SysTick->CTRL, LL_SYSTICK_CLKSOURCE_HCLK); +} + +/** + * @brief Enable SysTick exception request + * @rmtoll STK_CTRL TICKINT LL_SYSTICK_EnableIT + * @retval None + */ +__STATIC_INLINE void LL_SYSTICK_EnableIT(void) +{ + SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk); +} + +/** + * @brief Disable SysTick exception request + * @rmtoll STK_CTRL TICKINT LL_SYSTICK_DisableIT + * @retval None + */ +__STATIC_INLINE void LL_SYSTICK_DisableIT(void) +{ + CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk); +} + +/** + * @brief Checks if the SYSTICK interrupt is enabled or disabled. + * @rmtoll STK_CTRL TICKINT LL_SYSTICK_IsEnabledIT + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSTICK_IsEnabledIT(void) +{ + return (READ_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk) == (SysTick_CTRL_TICKINT_Msk)); +} + +/** + * @} + */ + +/** @defgroup CORTEX_LL_EF_LOW_POWER_MODE LOW POWER MODE + * @{ + */ + +/** + * @brief Processor uses sleep as its low power mode + * @rmtoll SCB_SCR SLEEPDEEP LL_LPM_EnableSleep + * @retval None + */ +__STATIC_INLINE void LL_LPM_EnableSleep(void) +{ + /* Clear SLEEPDEEP bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + +/** + * @brief Processor uses deep sleep as its low power mode + * @rmtoll SCB_SCR SLEEPDEEP LL_LPM_EnableDeepSleep + * @retval None + */ +__STATIC_INLINE void LL_LPM_EnableDeepSleep(void) +{ + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); +} + +/** + * @brief Configures sleep-on-exit when returning from Handler mode to Thread mode. + * @note Setting this bit to 1 enables an interrupt-driven application to avoid returning to an + * empty main application. + * @rmtoll SCB_SCR SLEEPONEXIT LL_LPM_EnableSleepOnExit + * @retval None + */ +__STATIC_INLINE void LL_LPM_EnableSleepOnExit(void) +{ + /* Set SLEEPONEXIT bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); +} + +/** + * @brief Do not sleep when returning to Thread mode. + * @rmtoll SCB_SCR SLEEPONEXIT LL_LPM_DisableSleepOnExit + * @retval None + */ +__STATIC_INLINE void LL_LPM_DisableSleepOnExit(void) +{ + /* Clear SLEEPONEXIT bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk)); +} + +/** + * @brief Enabled events and all interrupts, including disabled interrupts, can wakeup the + * processor. + * @rmtoll SCB_SCR SEVEONPEND LL_LPM_EnableEventOnPend + * @retval None + */ +__STATIC_INLINE void LL_LPM_EnableEventOnPend(void) +{ + /* Set SEVEONPEND bit of Cortex System Control Register */ + SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); +} + +/** + * @brief Only enabled interrupts or events can wakeup the processor, disabled interrupts are + * excluded + * @rmtoll SCB_SCR SEVEONPEND LL_LPM_DisableEventOnPend + * @retval None + */ +__STATIC_INLINE void LL_LPM_DisableEventOnPend(void) +{ + /* Clear SEVEONPEND bit of Cortex System Control Register */ + CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk)); +} + +/** + * @} + */ + +/** @defgroup CORTEX_LL_EF_HANDLER HANDLER + * @{ + */ + +/** + * @brief Enable a fault in System handler control register (SHCSR) + * @rmtoll SCB_SHCSR MEMFAULTENA LL_HANDLER_EnableFault + * @param Fault This parameter can be a combination of the following values: + * @arg @ref LL_HANDLER_FAULT_USG + * @arg @ref LL_HANDLER_FAULT_BUS + * @arg @ref LL_HANDLER_FAULT_MEM + * @retval None + */ +__STATIC_INLINE void LL_HANDLER_EnableFault(uint32_t Fault) +{ + /* Enable the system handler fault */ + SET_BIT(SCB->SHCSR, Fault); +} + +/** + * @brief Disable a fault in System handler control register (SHCSR) + * @rmtoll SCB_SHCSR MEMFAULTENA LL_HANDLER_DisableFault + * @param Fault This parameter can be a combination of the following values: + * @arg @ref LL_HANDLER_FAULT_USG + * @arg @ref LL_HANDLER_FAULT_BUS + * @arg @ref LL_HANDLER_FAULT_MEM + * @retval None + */ +__STATIC_INLINE void LL_HANDLER_DisableFault(uint32_t Fault) +{ + /* Disable the system handler fault */ + CLEAR_BIT(SCB->SHCSR, Fault); +} + +/** + * @} + */ + +/** @defgroup CORTEX_LL_EF_MCU_INFO MCU INFO + * @{ + */ + +/** + * @brief Get Implementer code + * @rmtoll SCB_CPUID IMPLEMENTER LL_CPUID_GetImplementer + * @retval Value should be equal to 0x41 for ARM + */ +__STATIC_INLINE uint32_t LL_CPUID_GetImplementer(void) +{ + return (uint32_t)(READ_BIT(SCB->CPUID, SCB_CPUID_IMPLEMENTER_Msk) >> SCB_CPUID_IMPLEMENTER_Pos); +} + +/** + * @brief Get Variant number (The r value in the rnpn product revision identifier) + * @rmtoll SCB_CPUID VARIANT LL_CPUID_GetVariant + * @retval Value between 0 and 255 (0x0: revision 0) + */ +__STATIC_INLINE uint32_t LL_CPUID_GetVariant(void) +{ + return (uint32_t)(READ_BIT(SCB->CPUID, SCB_CPUID_VARIANT_Msk) >> SCB_CPUID_VARIANT_Pos); +} + +/** + * @brief Get Constant number + * @rmtoll SCB_CPUID ARCHITECTURE LL_CPUID_GetConstant + * @retval Value should be equal to 0xF for Cortex-M4 devices + */ +__STATIC_INLINE uint32_t LL_CPUID_GetConstant(void) +{ + return (uint32_t)(READ_BIT(SCB->CPUID, SCB_CPUID_ARCHITECTURE_Msk) >> SCB_CPUID_ARCHITECTURE_Pos); +} + +/** + * @brief Get Part number + * @rmtoll SCB_CPUID PARTNO LL_CPUID_GetParNo + * @retval Value should be equal to 0xC24 for Cortex-M4 + */ +__STATIC_INLINE uint32_t LL_CPUID_GetParNo(void) +{ + return (uint32_t)(READ_BIT(SCB->CPUID, SCB_CPUID_PARTNO_Msk) >> SCB_CPUID_PARTNO_Pos); +} + +/** + * @brief Get Revision number (The p value in the rnpn product revision identifier, indicates patch release) + * @rmtoll SCB_CPUID REVISION LL_CPUID_GetRevision + * @retval Value between 0 and 255 (0x1: patch 1) + */ +__STATIC_INLINE uint32_t LL_CPUID_GetRevision(void) +{ + return (uint32_t)(READ_BIT(SCB->CPUID, SCB_CPUID_REVISION_Msk) >> SCB_CPUID_REVISION_Pos); +} + +/** + * @} + */ + +#if __MPU_PRESENT +/** @defgroup CORTEX_LL_EF_MPU MPU + * @{ + */ + +/** + * @brief Enable MPU with input options + * @rmtoll MPU_CTRL ENABLE LL_MPU_Enable + * @param Options This parameter can be one of the following values: + * @arg @ref LL_MPU_CTRL_HFNMI_PRIVDEF_NONE + * @arg @ref LL_MPU_CTRL_HARDFAULT_NMI + * @arg @ref LL_MPU_CTRL_PRIVILEGED_DEFAULT + * @arg @ref LL_MPU_CTRL_HFNMI_PRIVDEF + * @retval None + */ +__STATIC_INLINE void LL_MPU_Enable(uint32_t Options) +{ + /* Enable the MPU*/ + WRITE_REG(MPU->CTRL, (MPU_CTRL_ENABLE_Msk | Options)); + /* Ensure MPU settings take effects */ + __DSB(); + /* Sequence instruction fetches using update settings */ + __ISB(); +} + +/** + * @brief Disable MPU + * @rmtoll MPU_CTRL ENABLE LL_MPU_Disable + * @retval None + */ +__STATIC_INLINE void LL_MPU_Disable(void) +{ + /* Make sure outstanding transfers are done */ + __DMB(); + /* Disable MPU*/ + WRITE_REG(MPU->CTRL, 0U); +} + +/** + * @brief Check if MPU is enabled or not + * @rmtoll MPU_CTRL ENABLE LL_MPU_IsEnabled + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_MPU_IsEnabled(void) +{ + return (READ_BIT(MPU->CTRL, MPU_CTRL_ENABLE_Msk) == (MPU_CTRL_ENABLE_Msk)); +} + +/** + * @brief Enable a MPU region + * @rmtoll MPU_RASR ENABLE LL_MPU_EnableRegion + * @param Region This parameter can be one of the following values: + * @arg @ref LL_MPU_REGION_NUMBER0 + * @arg @ref LL_MPU_REGION_NUMBER1 + * @arg @ref LL_MPU_REGION_NUMBER2 + * @arg @ref LL_MPU_REGION_NUMBER3 + * @arg @ref LL_MPU_REGION_NUMBER4 + * @arg @ref LL_MPU_REGION_NUMBER5 + * @arg @ref LL_MPU_REGION_NUMBER6 + * @arg @ref LL_MPU_REGION_NUMBER7 + * @retval None + */ +__STATIC_INLINE void LL_MPU_EnableRegion(uint32_t Region) +{ + /* Set Region number */ + WRITE_REG(MPU->RNR, Region); + /* Enable the MPU region */ + SET_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk); +} + +/** + * @brief Configure and enable a region + * @rmtoll MPU_RNR REGION LL_MPU_ConfigRegion\n + * MPU_RBAR REGION LL_MPU_ConfigRegion\n + * MPU_RBAR ADDR LL_MPU_ConfigRegion\n + * MPU_RASR XN LL_MPU_ConfigRegion\n + * MPU_RASR AP LL_MPU_ConfigRegion\n + * MPU_RASR S LL_MPU_ConfigRegion\n + * MPU_RASR C LL_MPU_ConfigRegion\n + * MPU_RASR B LL_MPU_ConfigRegion\n + * MPU_RASR SIZE LL_MPU_ConfigRegion + * @param Region This parameter can be one of the following values: + * @arg @ref LL_MPU_REGION_NUMBER0 + * @arg @ref LL_MPU_REGION_NUMBER1 + * @arg @ref LL_MPU_REGION_NUMBER2 + * @arg @ref LL_MPU_REGION_NUMBER3 + * @arg @ref LL_MPU_REGION_NUMBER4 + * @arg @ref LL_MPU_REGION_NUMBER5 + * @arg @ref LL_MPU_REGION_NUMBER6 + * @arg @ref LL_MPU_REGION_NUMBER7 + * @param Address Value of region base address + * @param SubRegionDisable Sub-region disable value between Min_Data = 0x00 and Max_Data = 0xFF + * @param Attributes This parameter can be a combination of the following values: + * @arg @ref LL_MPU_REGION_SIZE_32B or @ref LL_MPU_REGION_SIZE_64B or @ref LL_MPU_REGION_SIZE_128B or @ref LL_MPU_REGION_SIZE_256B or @ref LL_MPU_REGION_SIZE_512B + * or @ref LL_MPU_REGION_SIZE_1KB or @ref LL_MPU_REGION_SIZE_2KB or @ref LL_MPU_REGION_SIZE_4KB or @ref LL_MPU_REGION_SIZE_8KB or @ref LL_MPU_REGION_SIZE_16KB + * or @ref LL_MPU_REGION_SIZE_32KB or @ref LL_MPU_REGION_SIZE_64KB or @ref LL_MPU_REGION_SIZE_128KB or @ref LL_MPU_REGION_SIZE_256KB or @ref LL_MPU_REGION_SIZE_512KB + * or @ref LL_MPU_REGION_SIZE_1MB or @ref LL_MPU_REGION_SIZE_2MB or @ref LL_MPU_REGION_SIZE_4MB or @ref LL_MPU_REGION_SIZE_8MB or @ref LL_MPU_REGION_SIZE_16MB + * or @ref LL_MPU_REGION_SIZE_32MB or @ref LL_MPU_REGION_SIZE_64MB or @ref LL_MPU_REGION_SIZE_128MB or @ref LL_MPU_REGION_SIZE_256MB or @ref LL_MPU_REGION_SIZE_512MB + * or @ref LL_MPU_REGION_SIZE_1GB or @ref LL_MPU_REGION_SIZE_2GB or @ref LL_MPU_REGION_SIZE_4GB + * @arg @ref LL_MPU_REGION_NO_ACCESS or @ref LL_MPU_REGION_PRIV_RW or @ref LL_MPU_REGION_PRIV_RW_URO or @ref LL_MPU_REGION_FULL_ACCESS + * or @ref LL_MPU_REGION_PRIV_RO or @ref LL_MPU_REGION_PRIV_RO_URO + * @arg @ref LL_MPU_TEX_LEVEL0 or @ref LL_MPU_TEX_LEVEL1 or @ref LL_MPU_TEX_LEVEL2 or @ref LL_MPU_TEX_LEVEL4 + * @arg @ref LL_MPU_INSTRUCTION_ACCESS_ENABLE or @ref LL_MPU_INSTRUCTION_ACCESS_DISABLE + * @arg @ref LL_MPU_ACCESS_SHAREABLE or @ref LL_MPU_ACCESS_NOT_SHAREABLE + * @arg @ref LL_MPU_ACCESS_CACHEABLE or @ref LL_MPU_ACCESS_NOT_CACHEABLE + * @arg @ref LL_MPU_ACCESS_BUFFERABLE or @ref LL_MPU_ACCESS_NOT_BUFFERABLE + * @retval None + */ +__STATIC_INLINE void LL_MPU_ConfigRegion(uint32_t Region, uint32_t SubRegionDisable, uint32_t Address, uint32_t Attributes) +{ + /* Set Region number */ + WRITE_REG(MPU->RNR, Region); + /* Set base address */ + WRITE_REG(MPU->RBAR, (Address & 0xFFFFFFE0U)); + /* Configure MPU */ + WRITE_REG(MPU->RASR, (MPU_RASR_ENABLE_Msk | Attributes | SubRegionDisable << MPU_RASR_SRD_Pos)); +} + +/** + * @brief Disable a region + * @rmtoll MPU_RNR REGION LL_MPU_DisableRegion\n + * MPU_RASR ENABLE LL_MPU_DisableRegion + * @param Region This parameter can be one of the following values: + * @arg @ref LL_MPU_REGION_NUMBER0 + * @arg @ref LL_MPU_REGION_NUMBER1 + * @arg @ref LL_MPU_REGION_NUMBER2 + * @arg @ref LL_MPU_REGION_NUMBER3 + * @arg @ref LL_MPU_REGION_NUMBER4 + * @arg @ref LL_MPU_REGION_NUMBER5 + * @arg @ref LL_MPU_REGION_NUMBER6 + * @arg @ref LL_MPU_REGION_NUMBER7 + * @retval None + */ +__STATIC_INLINE void LL_MPU_DisableRegion(uint32_t Region) +{ + /* Set Region number */ + WRITE_REG(MPU->RNR, Region); + /* Disable the MPU region */ + CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk); +} + +/** + * @} + */ + +#endif /* __MPU_PRESENT */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_CORTEX_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_crs.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_crs.h new file mode 100644 index 0000000..6714617 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_crs.h @@ -0,0 +1,785 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_crs.h + * @author MCD Application Team + * @brief Header file of CRS 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 STM32L4xx_LL_CRS_H +#define STM32L4xx_LL_CRS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(CRS) + +/** @defgroup CRS_LL CRS + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CRS_LL_Exported_Constants CRS Exported Constants + * @{ + */ + +/** @defgroup CRS_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_CRS_ReadReg function + * @{ + */ +#define LL_CRS_ISR_SYNCOKF CRS_ISR_SYNCOKF +#define LL_CRS_ISR_SYNCWARNF CRS_ISR_SYNCWARNF +#define LL_CRS_ISR_ERRF CRS_ISR_ERRF +#define LL_CRS_ISR_ESYNCF CRS_ISR_ESYNCF +#define LL_CRS_ISR_SYNCERR CRS_ISR_SYNCERR +#define LL_CRS_ISR_SYNCMISS CRS_ISR_SYNCMISS +#define LL_CRS_ISR_TRIMOVF CRS_ISR_TRIMOVF +/** + * @} + */ + +/** @defgroup CRS_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_CRS_ReadReg and LL_CRS_WriteReg functions + * @{ + */ +#define LL_CRS_CR_SYNCOKIE CRS_CR_SYNCOKIE +#define LL_CRS_CR_SYNCWARNIE CRS_CR_SYNCWARNIE +#define LL_CRS_CR_ERRIE CRS_CR_ERRIE +#define LL_CRS_CR_ESYNCIE CRS_CR_ESYNCIE +/** + * @} + */ + +/** @defgroup CRS_LL_EC_SYNC_DIV Synchronization Signal Divider + * @{ + */ +#define LL_CRS_SYNC_DIV_1 ((uint32_t)0x00U) /*!< Synchro Signal not divided (default) */ +#define LL_CRS_SYNC_DIV_2 CRS_CFGR_SYNCDIV_0 /*!< Synchro Signal divided by 2 */ +#define LL_CRS_SYNC_DIV_4 CRS_CFGR_SYNCDIV_1 /*!< Synchro Signal divided by 4 */ +#define LL_CRS_SYNC_DIV_8 (CRS_CFGR_SYNCDIV_1 | CRS_CFGR_SYNCDIV_0) /*!< Synchro Signal divided by 8 */ +#define LL_CRS_SYNC_DIV_16 CRS_CFGR_SYNCDIV_2 /*!< Synchro Signal divided by 16 */ +#define LL_CRS_SYNC_DIV_32 (CRS_CFGR_SYNCDIV_2 | CRS_CFGR_SYNCDIV_0) /*!< Synchro Signal divided by 32 */ +#define LL_CRS_SYNC_DIV_64 (CRS_CFGR_SYNCDIV_2 | CRS_CFGR_SYNCDIV_1) /*!< Synchro Signal divided by 64 */ +#define LL_CRS_SYNC_DIV_128 CRS_CFGR_SYNCDIV /*!< Synchro Signal divided by 128 */ +/** + * @} + */ + +/** @defgroup CRS_LL_EC_SYNC_SOURCE Synchronization Signal Source + * @{ + */ +#define LL_CRS_SYNC_SOURCE_GPIO ((uint32_t)0x00U) /*!< Synchro Signal source GPIO */ +#define LL_CRS_SYNC_SOURCE_LSE CRS_CFGR_SYNCSRC_0 /*!< Synchro Signal source LSE */ +#define LL_CRS_SYNC_SOURCE_USB CRS_CFGR_SYNCSRC_1 /*!< Synchro Signal source USB SOF (default)*/ +/** + * @} + */ + +/** @defgroup CRS_LL_EC_SYNC_POLARITY Synchronization Signal Polarity + * @{ + */ +#define LL_CRS_SYNC_POLARITY_RISING ((uint32_t)0x00U) /*!< Synchro Active on rising edge (default) */ +#define LL_CRS_SYNC_POLARITY_FALLING CRS_CFGR_SYNCPOL /*!< Synchro Active on falling edge */ +/** + * @} + */ + +/** @defgroup CRS_LL_EC_FREQERRORDIR Frequency Error Direction + * @{ + */ +#define LL_CRS_FREQ_ERROR_DIR_UP ((uint32_t)0x00U) /*!< Upcounting direction, the actual frequency is above the target */ +#define LL_CRS_FREQ_ERROR_DIR_DOWN ((uint32_t)CRS_ISR_FEDIR) /*!< Downcounting direction, the actual frequency is below the target */ +/** + * @} + */ + +/** @defgroup CRS_LL_EC_DEFAULTVALUES Default Values + * @{ + */ +/** + * @brief Reset value of the RELOAD field + * @note The reset value of the RELOAD field corresponds to a target frequency of 48 MHz + * and a synchronization signal frequency of 1 kHz (SOF signal from USB) + */ +#define LL_CRS_RELOADVALUE_DEFAULT ((uint32_t)0xBB7FU) + +/** + * @brief Reset value of Frequency error limit. + */ +#define LL_CRS_ERRORLIMIT_DEFAULT ((uint32_t)0x22U) + +/** + * @brief Reset value of the HSI48 Calibration field + * @note The default value is 64 for STM32L412xx/L422xx, 32 otherwise, which corresponds + * to the middle of the trimming interval. + * The trimming step is around 67 kHz between two consecutive TRIM steps. + * A higher TRIM value corresponds to a higher output frequency + */ +#if defined (STM32L412xx) || defined (STM32L422xx) +#define LL_CRS_HSI48CALIBRATION_DEFAULT ((uint32_t)64U) +#else +#define LL_CRS_HSI48CALIBRATION_DEFAULT ((uint32_t)32U) +#endif +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup CRS_LL_Exported_Macros CRS Exported Macros + * @{ + */ + +/** @defgroup CRS_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in CRS register + * @param __INSTANCE__ CRS Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_CRS_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in CRS register + * @param __INSTANCE__ CRS Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_CRS_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup CRS_LL_EM_Exported_Macros_Calculate_Reload Exported_Macros_Calculate_Reload + * @{ + */ + +/** + * @brief Macro to calculate reload value to be set in CRS register according to target and sync frequencies + * @note The RELOAD value should be selected according to the ratio between + * the target frequency and the frequency of the synchronization source after + * prescaling. It is then decreased by one in order to reach the expected + * synchronization on the zero value. The formula is the following: + * RELOAD = (fTARGET / fSYNC) -1 + * @param __FTARGET__ Target frequency (value in Hz) + * @param __FSYNC__ Synchronization signal frequency (value in Hz) + * @retval Reload value (in Hz) + */ +#define __LL_CRS_CALC_CALCULATE_RELOADVALUE(__FTARGET__, __FSYNC__) (((__FTARGET__) / (__FSYNC__)) - 1U) + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CRS_LL_Exported_Functions CRS Exported Functions + * @{ + */ + +/** @defgroup CRS_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable Frequency error counter + * @note When this bit is set, the CRS_CFGR register is write-protected and cannot be modified + * @rmtoll CR CEN LL_CRS_EnableFreqErrorCounter + * @retval None + */ +__STATIC_INLINE void LL_CRS_EnableFreqErrorCounter(void) +{ + SET_BIT(CRS->CR, CRS_CR_CEN); +} + +/** + * @brief Disable Frequency error counter + * @rmtoll CR CEN LL_CRS_DisableFreqErrorCounter + * @retval None + */ +__STATIC_INLINE void LL_CRS_DisableFreqErrorCounter(void) +{ + CLEAR_BIT(CRS->CR, CRS_CR_CEN); +} + +/** + * @brief Check if Frequency error counter is enabled or not + * @rmtoll CR CEN LL_CRS_IsEnabledFreqErrorCounter + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsEnabledFreqErrorCounter(void) +{ + return (READ_BIT(CRS->CR, CRS_CR_CEN) == (CRS_CR_CEN)); +} + +/** + * @brief Enable Automatic trimming counter + * @rmtoll CR AUTOTRIMEN LL_CRS_EnableAutoTrimming + * @retval None + */ +__STATIC_INLINE void LL_CRS_EnableAutoTrimming(void) +{ + SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN); +} + +/** + * @brief Disable Automatic trimming counter + * @rmtoll CR AUTOTRIMEN LL_CRS_DisableAutoTrimming + * @retval None + */ +__STATIC_INLINE void LL_CRS_DisableAutoTrimming(void) +{ + CLEAR_BIT(CRS->CR, CRS_CR_AUTOTRIMEN); +} + +/** + * @brief Check if Automatic trimming is enabled or not + * @rmtoll CR AUTOTRIMEN LL_CRS_IsEnabledAutoTrimming + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsEnabledAutoTrimming(void) +{ + return (READ_BIT(CRS->CR, CRS_CR_AUTOTRIMEN) == (CRS_CR_AUTOTRIMEN)); +} + +/** + * @brief Set HSI48 oscillator smooth trimming + * @note When the AUTOTRIMEN bit is set, this field is controlled by hardware and is read-only + * @rmtoll CR TRIM LL_CRS_SetHSI48SmoothTrimming + * @param Value a number between Min_Data = 0 and Max_Data = 127 for STM32L412xx/L422xx or 63 otherwise + * @note Default value can be set thanks to @ref LL_CRS_HSI48CALIBRATION_DEFAULT + * @retval None + */ +__STATIC_INLINE void LL_CRS_SetHSI48SmoothTrimming(uint32_t Value) +{ + MODIFY_REG(CRS->CR, CRS_CR_TRIM, Value << CRS_CR_TRIM_Pos); +} + +/** + * @brief Get HSI48 oscillator smooth trimming + * @rmtoll CR TRIM LL_CRS_GetHSI48SmoothTrimming + * @retval a number between Min_Data = 0 and Max_Data = 127 for STM32L412xx/L422xx or 63 otherwise + */ +__STATIC_INLINE uint32_t LL_CRS_GetHSI48SmoothTrimming(void) +{ + return (uint32_t)(READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos); +} + +/** + * @brief Set counter reload value + * @rmtoll CFGR RELOAD LL_CRS_SetReloadCounter + * @param Value a number between Min_Data = 0 and Max_Data = 0xFFFF + * @note Default value can be set thanks to @ref LL_CRS_RELOADVALUE_DEFAULT + * Otherwise it can be calculated in using macro @ref __LL_CRS_CALC_CALCULATE_RELOADVALUE (_FTARGET_, _FSYNC_) + * @retval None + */ +__STATIC_INLINE void LL_CRS_SetReloadCounter(uint32_t Value) +{ + MODIFY_REG(CRS->CFGR, CRS_CFGR_RELOAD, Value); +} + +/** + * @brief Get counter reload value + * @rmtoll CFGR RELOAD LL_CRS_GetReloadCounter + * @retval a number between Min_Data = 0 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_CRS_GetReloadCounter(void) +{ + return (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD)); +} + +/** + * @brief Set frequency error limit + * @rmtoll CFGR FELIM LL_CRS_SetFreqErrorLimit + * @param Value a number between Min_Data = 0 and Max_Data = 255 + * @note Default value can be set thanks to @ref LL_CRS_ERRORLIMIT_DEFAULT + * @retval None + */ +__STATIC_INLINE void LL_CRS_SetFreqErrorLimit(uint32_t Value) +{ + MODIFY_REG(CRS->CFGR, CRS_CFGR_FELIM, Value << CRS_CFGR_FELIM_Pos); +} + +/** + * @brief Get frequency error limit + * @rmtoll CFGR FELIM LL_CRS_GetFreqErrorLimit + * @retval A number between Min_Data = 0 and Max_Data = 255 + */ +__STATIC_INLINE uint32_t LL_CRS_GetFreqErrorLimit(void) +{ + return (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_FELIM) >> CRS_CFGR_FELIM_Pos); +} + +/** + * @brief Set division factor for SYNC signal + * @rmtoll CFGR SYNCDIV LL_CRS_SetSyncDivider + * @param Divider This parameter can be one of the following values: + * @arg @ref LL_CRS_SYNC_DIV_1 + * @arg @ref LL_CRS_SYNC_DIV_2 + * @arg @ref LL_CRS_SYNC_DIV_4 + * @arg @ref LL_CRS_SYNC_DIV_8 + * @arg @ref LL_CRS_SYNC_DIV_16 + * @arg @ref LL_CRS_SYNC_DIV_32 + * @arg @ref LL_CRS_SYNC_DIV_64 + * @arg @ref LL_CRS_SYNC_DIV_128 + * @retval None + */ +__STATIC_INLINE void LL_CRS_SetSyncDivider(uint32_t Divider) +{ + MODIFY_REG(CRS->CFGR, CRS_CFGR_SYNCDIV, Divider); +} + +/** + * @brief Get division factor for SYNC signal + * @rmtoll CFGR SYNCDIV LL_CRS_GetSyncDivider + * @retval Returned value can be one of the following values: + * @arg @ref LL_CRS_SYNC_DIV_1 + * @arg @ref LL_CRS_SYNC_DIV_2 + * @arg @ref LL_CRS_SYNC_DIV_4 + * @arg @ref LL_CRS_SYNC_DIV_8 + * @arg @ref LL_CRS_SYNC_DIV_16 + * @arg @ref LL_CRS_SYNC_DIV_32 + * @arg @ref LL_CRS_SYNC_DIV_64 + * @arg @ref LL_CRS_SYNC_DIV_128 + */ +__STATIC_INLINE uint32_t LL_CRS_GetSyncDivider(void) +{ + return (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_SYNCDIV)); +} + +/** + * @brief Set SYNC signal source + * @rmtoll CFGR SYNCSRC LL_CRS_SetSyncSignalSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_CRS_SYNC_SOURCE_GPIO + * @arg @ref LL_CRS_SYNC_SOURCE_LSE + * @arg @ref LL_CRS_SYNC_SOURCE_USB + * @retval None + */ +__STATIC_INLINE void LL_CRS_SetSyncSignalSource(uint32_t Source) +{ + MODIFY_REG(CRS->CFGR, CRS_CFGR_SYNCSRC, Source); +} + +/** + * @brief Get SYNC signal source + * @rmtoll CFGR SYNCSRC LL_CRS_GetSyncSignalSource + * @retval Returned value can be one of the following values: + * @arg @ref LL_CRS_SYNC_SOURCE_GPIO + * @arg @ref LL_CRS_SYNC_SOURCE_LSE + * @arg @ref LL_CRS_SYNC_SOURCE_USB + */ +__STATIC_INLINE uint32_t LL_CRS_GetSyncSignalSource(void) +{ + return (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_SYNCSRC)); +} + +/** + * @brief Set input polarity for the SYNC signal source + * @rmtoll CFGR SYNCPOL LL_CRS_SetSyncPolarity + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_CRS_SYNC_POLARITY_RISING + * @arg @ref LL_CRS_SYNC_POLARITY_FALLING + * @retval None + */ +__STATIC_INLINE void LL_CRS_SetSyncPolarity(uint32_t Polarity) +{ + MODIFY_REG(CRS->CFGR, CRS_CFGR_SYNCPOL, Polarity); +} + +/** + * @brief Get input polarity for the SYNC signal source + * @rmtoll CFGR SYNCPOL LL_CRS_GetSyncPolarity + * @retval Returned value can be one of the following values: + * @arg @ref LL_CRS_SYNC_POLARITY_RISING + * @arg @ref LL_CRS_SYNC_POLARITY_FALLING + */ +__STATIC_INLINE uint32_t LL_CRS_GetSyncPolarity(void) +{ + return (uint32_t)(READ_BIT(CRS->CFGR, CRS_CFGR_SYNCPOL)); +} + +/** + * @brief Configure CRS for the synchronization + * @rmtoll CR TRIM LL_CRS_ConfigSynchronization\n + * CFGR RELOAD LL_CRS_ConfigSynchronization\n + * CFGR FELIM LL_CRS_ConfigSynchronization\n + * CFGR SYNCDIV LL_CRS_ConfigSynchronization\n + * CFGR SYNCSRC LL_CRS_ConfigSynchronization\n + * CFGR SYNCPOL LL_CRS_ConfigSynchronization + * @param HSI48CalibrationValue a number between Min_Data = 0 and Max_Data = 127 for STM32L412xx/L422xx or 63 otherwise + * @param ErrorLimitValue a number between Min_Data = 0 and Max_Data = 0xFFFF + * @param ReloadValue a number between Min_Data = 0 and Max_Data = 255 + * @param Settings This parameter can be a combination of the following values: + * @arg @ref LL_CRS_SYNC_DIV_1 or @ref LL_CRS_SYNC_DIV_2 or @ref LL_CRS_SYNC_DIV_4 or @ref LL_CRS_SYNC_DIV_8 + * or @ref LL_CRS_SYNC_DIV_16 or @ref LL_CRS_SYNC_DIV_32 or @ref LL_CRS_SYNC_DIV_64 or @ref LL_CRS_SYNC_DIV_128 + * @arg @ref LL_CRS_SYNC_SOURCE_GPIO or @ref LL_CRS_SYNC_SOURCE_LSE or @ref LL_CRS_SYNC_SOURCE_USB + * @arg @ref LL_CRS_SYNC_POLARITY_RISING or @ref LL_CRS_SYNC_POLARITY_FALLING + * @retval None + */ +__STATIC_INLINE void LL_CRS_ConfigSynchronization(uint32_t HSI48CalibrationValue, uint32_t ErrorLimitValue, uint32_t ReloadValue, uint32_t Settings) +{ + MODIFY_REG(CRS->CR, CRS_CR_TRIM, HSI48CalibrationValue << CRS_CR_TRIM_Pos); + MODIFY_REG(CRS->CFGR, + CRS_CFGR_RELOAD | CRS_CFGR_FELIM | CRS_CFGR_SYNCDIV | CRS_CFGR_SYNCSRC | CRS_CFGR_SYNCPOL, + ReloadValue | (ErrorLimitValue << CRS_CFGR_FELIM_Pos) | Settings); +} + +/** + * @} + */ + +/** @defgroup CRS_LL_EF_CRS_Management CRS_Management + * @{ + */ + +/** + * @brief Generate software SYNC event + * @rmtoll CR SWSYNC LL_CRS_GenerateEvent_SWSYNC + * @retval None + */ +__STATIC_INLINE void LL_CRS_GenerateEvent_SWSYNC(void) +{ + SET_BIT(CRS->CR, CRS_CR_SWSYNC); +} + +/** + * @brief Get the frequency error direction latched in the time of the last + * SYNC event + * @rmtoll ISR FEDIR LL_CRS_GetFreqErrorDirection + * @retval Returned value can be one of the following values: + * @arg @ref LL_CRS_FREQ_ERROR_DIR_UP + * @arg @ref LL_CRS_FREQ_ERROR_DIR_DOWN + */ +__STATIC_INLINE uint32_t LL_CRS_GetFreqErrorDirection(void) +{ + return (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FEDIR)); +} + +/** + * @brief Get the frequency error counter value latched in the time of the last SYNC event + * @rmtoll ISR FECAP LL_CRS_GetFreqErrorCapture + * @retval A number between Min_Data = 0x0000 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_CRS_GetFreqErrorCapture(void) +{ + return (uint32_t)(READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos); +} + +/** + * @} + */ + +/** @defgroup CRS_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Check if SYNC event OK signal occurred or not + * @rmtoll ISR SYNCOKF LL_CRS_IsActiveFlag_SYNCOK + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_SYNCOK(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_SYNCOKF) == (CRS_ISR_SYNCOKF)); +} + +/** + * @brief Check if SYNC warning signal occurred or not + * @rmtoll ISR SYNCWARNF LL_CRS_IsActiveFlag_SYNCWARN + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_SYNCWARN(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_SYNCWARNF) == (CRS_ISR_SYNCWARNF)); +} + +/** + * @brief Check if Synchronization or trimming error signal occurred or not + * @rmtoll ISR ERRF LL_CRS_IsActiveFlag_ERR + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_ERR(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_ERRF) == (CRS_ISR_ERRF)); +} + +/** + * @brief Check if Expected SYNC signal occurred or not + * @rmtoll ISR ESYNCF LL_CRS_IsActiveFlag_ESYNC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_ESYNC(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_ESYNCF) == (CRS_ISR_ESYNCF)); +} + +/** + * @brief Check if SYNC error signal occurred or not + * @rmtoll ISR SYNCERR LL_CRS_IsActiveFlag_SYNCERR + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_SYNCERR(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_SYNCERR) == (CRS_ISR_SYNCERR)); +} + +/** + * @brief Check if SYNC missed error signal occurred or not + * @rmtoll ISR SYNCMISS LL_CRS_IsActiveFlag_SYNCMISS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_SYNCMISS(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_SYNCMISS) == (CRS_ISR_SYNCMISS)); +} + +/** + * @brief Check if Trimming overflow or underflow occurred or not + * @rmtoll ISR TRIMOVF LL_CRS_IsActiveFlag_TRIMOVF + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsActiveFlag_TRIMOVF(void) +{ + return (READ_BIT(CRS->ISR, CRS_ISR_TRIMOVF) == (CRS_ISR_TRIMOVF)); +} + +/** + * @brief Clear the SYNC event OK flag + * @rmtoll ICR SYNCOKC LL_CRS_ClearFlag_SYNCOK + * @retval None + */ +__STATIC_INLINE void LL_CRS_ClearFlag_SYNCOK(void) +{ + WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC); +} + +/** + * @brief Clear the SYNC warning flag + * @rmtoll ICR SYNCWARNC LL_CRS_ClearFlag_SYNCWARN + * @retval None + */ +__STATIC_INLINE void LL_CRS_ClearFlag_SYNCWARN(void) +{ + WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC); +} + +/** + * @brief Clear TRIMOVF, SYNCMISS and SYNCERR bits and consequently also + * the ERR flag + * @rmtoll ICR ERRC LL_CRS_ClearFlag_ERR + * @retval None + */ +__STATIC_INLINE void LL_CRS_ClearFlag_ERR(void) +{ + WRITE_REG(CRS->ICR, CRS_ICR_ERRC); +} + +/** + * @brief Clear Expected SYNC flag + * @rmtoll ICR ESYNCC LL_CRS_ClearFlag_ESYNC + * @retval None + */ +__STATIC_INLINE void LL_CRS_ClearFlag_ESYNC(void) +{ + WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC); +} + +/** + * @} + */ + +/** @defgroup CRS_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable SYNC event OK interrupt + * @rmtoll CR SYNCOKIE LL_CRS_EnableIT_SYNCOK + * @retval None + */ +__STATIC_INLINE void LL_CRS_EnableIT_SYNCOK(void) +{ + SET_BIT(CRS->CR, CRS_CR_SYNCOKIE); +} + +/** + * @brief Disable SYNC event OK interrupt + * @rmtoll CR SYNCOKIE LL_CRS_DisableIT_SYNCOK + * @retval None + */ +__STATIC_INLINE void LL_CRS_DisableIT_SYNCOK(void) +{ + CLEAR_BIT(CRS->CR, CRS_CR_SYNCOKIE); +} + +/** + * @brief Check if SYNC event OK interrupt is enabled or not + * @rmtoll CR SYNCOKIE LL_CRS_IsEnabledIT_SYNCOK + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsEnabledIT_SYNCOK(void) +{ + return (READ_BIT(CRS->CR, CRS_CR_SYNCOKIE) == (CRS_CR_SYNCOKIE)); +} + +/** + * @brief Enable SYNC warning interrupt + * @rmtoll CR SYNCWARNIE LL_CRS_EnableIT_SYNCWARN + * @retval None + */ +__STATIC_INLINE void LL_CRS_EnableIT_SYNCWARN(void) +{ + SET_BIT(CRS->CR, CRS_CR_SYNCWARNIE); +} + +/** + * @brief Disable SYNC warning interrupt + * @rmtoll CR SYNCWARNIE LL_CRS_DisableIT_SYNCWARN + * @retval None + */ +__STATIC_INLINE void LL_CRS_DisableIT_SYNCWARN(void) +{ + CLEAR_BIT(CRS->CR, CRS_CR_SYNCWARNIE); +} + +/** + * @brief Check if SYNC warning interrupt is enabled or not + * @rmtoll CR SYNCWARNIE LL_CRS_IsEnabledIT_SYNCWARN + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsEnabledIT_SYNCWARN(void) +{ + return (READ_BIT(CRS->CR, CRS_CR_SYNCWARNIE) == (CRS_CR_SYNCWARNIE)); +} + +/** + * @brief Enable Synchronization or trimming error interrupt + * @rmtoll CR ERRIE LL_CRS_EnableIT_ERR + * @retval None + */ +__STATIC_INLINE void LL_CRS_EnableIT_ERR(void) +{ + SET_BIT(CRS->CR, CRS_CR_ERRIE); +} + +/** + * @brief Disable Synchronization or trimming error interrupt + * @rmtoll CR ERRIE LL_CRS_DisableIT_ERR + * @retval None + */ +__STATIC_INLINE void LL_CRS_DisableIT_ERR(void) +{ + CLEAR_BIT(CRS->CR, CRS_CR_ERRIE); +} + +/** + * @brief Check if Synchronization or trimming error interrupt is enabled or not + * @rmtoll CR ERRIE LL_CRS_IsEnabledIT_ERR + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsEnabledIT_ERR(void) +{ + return (READ_BIT(CRS->CR, CRS_CR_ERRIE) == (CRS_CR_ERRIE)); +} + +/** + * @brief Enable Expected SYNC interrupt + * @rmtoll CR ESYNCIE LL_CRS_EnableIT_ESYNC + * @retval None + */ +__STATIC_INLINE void LL_CRS_EnableIT_ESYNC(void) +{ + SET_BIT(CRS->CR, CRS_CR_ESYNCIE); +} + +/** + * @brief Disable Expected SYNC interrupt + * @rmtoll CR ESYNCIE LL_CRS_DisableIT_ESYNC + * @retval None + */ +__STATIC_INLINE void LL_CRS_DisableIT_ESYNC(void) +{ + CLEAR_BIT(CRS->CR, CRS_CR_ESYNCIE); +} + +/** + * @brief Check if Expected SYNC interrupt is enabled or not + * @rmtoll CR ESYNCIE LL_CRS_IsEnabledIT_ESYNC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_CRS_IsEnabledIT_ESYNC(void) +{ + return (READ_BIT(CRS->CR, CRS_CR_ESYNCIE) == (CRS_CR_ESYNCIE)); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup CRS_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_CRS_DeInit(void); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(CRS) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_CRS_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dac.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dac.h new file mode 100644 index 0000000..b3f641c --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dac.h @@ -0,0 +1,1979 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_dac.h + * @author MCD Application Team + * @brief Header file of DAC 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 STM32L4xx_LL_DAC_H +#define STM32L4xx_LL_DAC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (DAC1) + +/** @defgroup DAC_LL DAC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup DAC_LL_Private_Constants DAC Private Constants + * @{ + */ + +/* Internal masks for DAC channels definition */ +/* To select into literal LL_DAC_CHANNEL_x the relevant bits for: */ +/* - channel bits position into registers CR, MCR, CCR, SHHR, SHRR */ +/* - channel bits position into register SWTRIG */ +/* - channel register offset of data holding register DHRx */ +/* - channel register offset of data output register DORx */ +/* - channel register offset of sample-and-hold sample time register SHSRx */ +#define DAC_CR_CH1_BITOFFSET 0U /* Position of channel bits into registers CR, MCR, CCR, SHHR, SHRR of channel 1 */ +#define DAC_CR_CH2_BITOFFSET 16U /* Position of channel bits into registers CR, MCR, CCR, SHHR, SHRR of channel 2 */ +#define DAC_CR_CHX_BITOFFSET_MASK (DAC_CR_CH1_BITOFFSET | DAC_CR_CH2_BITOFFSET) + +#define DAC_SWTR_CH1 (DAC_SWTRIGR_SWTRIG1) /* Channel bit into register SWTRIGR of channel 1. */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define DAC_SWTR_CH2 (DAC_SWTRIGR_SWTRIG2) /* Channel bit into register SWTRIGR of channel 2. */ +#define DAC_SWTR_CHX_MASK (DAC_SWTR_CH1 | DAC_SWTR_CH2) +#else +#define DAC_SWTR_CHX_MASK (DAC_SWTR_CH1) +#endif /* DAC_CHANNEL2_SUPPORT */ + +#define DAC_REG_DHR12R1_REGOFFSET 0x00000000U /* Register DHR12Rx channel 1 taken as reference */ +#define DAC_REG_DHR12L1_REGOFFSET 0x00100000U /* Register offset of DHR12Lx channel 1 versus DHR12Rx channel 1 (shifted left of 20 bits) */ +#define DAC_REG_DHR8R1_REGOFFSET 0x02000000U /* Register offset of DHR8Rx channel 1 versus DHR12Rx channel 1 (shifted left of 24 bits) */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define DAC_REG_DHR12R2_REGOFFSET 0x30000000U /* Register offset of DHR12Rx channel 2 versus DHR12Rx channel 1 (shifted left of 28 bits) */ +#define DAC_REG_DHR12L2_REGOFFSET 0x00400000U /* Register offset of DHR12Lx channel 2 versus DHR12Rx channel 1 (shifted left of 20 bits) */ +#define DAC_REG_DHR8R2_REGOFFSET 0x05000000U /* Register offset of DHR8Rx channel 2 versus DHR12Rx channel 1 (shifted left of 24 bits) */ +#endif /* DAC_CHANNEL2_SUPPORT */ +#define DAC_REG_DHR12RX_REGOFFSET_MASK 0xF0000000U +#define DAC_REG_DHR12LX_REGOFFSET_MASK 0x00F00000U +#define DAC_REG_DHR8RX_REGOFFSET_MASK 0x0F000000U +#define DAC_REG_DHRX_REGOFFSET_MASK (DAC_REG_DHR12RX_REGOFFSET_MASK | DAC_REG_DHR12LX_REGOFFSET_MASK | DAC_REG_DHR8RX_REGOFFSET_MASK) + +#define DAC_REG_DOR1_REGOFFSET 0x00000000U /* Register DORx channel 1 taken as reference */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define DAC_REG_DOR2_REGOFFSET 0x00000020U /* Register offset of DORx channel 1 versus DORx channel 2 (shifted left of 5 bits) */ +#define DAC_REG_DORX_REGOFFSET_MASK (DAC_REG_DOR1_REGOFFSET | DAC_REG_DOR2_REGOFFSET) +#else +#define DAC_REG_DORX_REGOFFSET_MASK (DAC_REG_DOR1_REGOFFSET) +#endif /* DAC_CHANNEL2_SUPPORT */ + +#define DAC_REG_SHSR1_REGOFFSET 0x00000000U /* Register SHSRx channel 1 taken as reference */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define DAC_REG_SHSR2_REGOFFSET 0x00000040U /* Register offset of SHSRx channel 1 versus SHSRx channel 2 (shifted left of 6 bits) */ +#define DAC_REG_SHSRX_REGOFFSET_MASK (DAC_REG_SHSR1_REGOFFSET | DAC_REG_SHSR2_REGOFFSET) +#else +#define DAC_REG_SHSRX_REGOFFSET_MASK (DAC_REG_SHSR1_REGOFFSET) +#endif /* DAC_CHANNEL2_SUPPORT */ + +#define DAC_REG_DHR_REGOFFSET_MASK_POSBIT0 0x0000000FU /* Mask of data hold registers offset (DHR12Rx, DHR12Lx, DHR8Rx, ...) when shifted to position 0 */ +#define DAC_REG_DORX_REGOFFSET_MASK_POSBIT0 0x00000001U /* Mask of DORx registers offset when shifted to position 0 */ +#define DAC_REG_SHSRX_REGOFFSET_MASK_POSBIT0 0x00000001U /* Mask of SHSRx registers offset when shifted to position 0 */ + +#define DAC_REG_DHR12RX_REGOFFSET_BITOFFSET_POS 28U /* Position of bits register offset of DHR12Rx channel 1 or 2 versus DHR12Rx channel 1 (shifted left of 28 bits) */ +#define DAC_REG_DHR12LX_REGOFFSET_BITOFFSET_POS 20U /* Position of bits register offset of DHR12Lx channel 1 or 2 versus DHR12Rx channel 1 (shifted left of 20 bits) */ +#define DAC_REG_DHR8RX_REGOFFSET_BITOFFSET_POS 24U /* Position of bits register offset of DHR8Rx channel 1 or 2 versus DHR12Rx channel 1 (shifted left of 24 bits) */ +#define DAC_REG_DORX_REGOFFSET_BITOFFSET_POS 5U /* Position of bits register offset of DORx channel 1 or 2 versus DORx channel 1 (shifted left of 5 bits) */ +#define DAC_REG_SHSRX_REGOFFSET_BITOFFSET_POS 6U /* Position of bits register offset of SHSRx channel 1 or 2 versus SHSRx channel 1 (shifted left of 6 bits) */ + +/* DAC registers bits positions */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define DAC_DHR12RD_DACC2DHR_BITOFFSET_POS DAC_DHR12RD_DACC2DHR_Pos +#define DAC_DHR12LD_DACC2DHR_BITOFFSET_POS DAC_DHR12LD_DACC2DHR_Pos +#define DAC_DHR8RD_DACC2DHR_BITOFFSET_POS DAC_DHR8RD_DACC2DHR_Pos +#endif /* DAC_CHANNEL2_SUPPORT */ + +/* Miscellaneous data */ +#define DAC_DIGITAL_SCALE_12BITS 4095U /* Full-scale digital value with a resolution of 12 bits (voltage range determined by analog voltage references Vref+ and Vref-, refer to reference manual) */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DAC_LL_Private_Macros DAC Private Macros + * @{ + */ + +/** + * @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 __DAC_PTR_REG_OFFSET(__REG__, __REG_OFFFSET__) \ + ((uint32_t *)((uint32_t) ((uint32_t)(&(__REG__)) + ((__REG_OFFFSET__) << 2U)))) + +/** + * @} + */ + + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DAC_LL_ES_INIT DAC Exported Init structure + * @{ + */ + +/** + * @brief Structure definition of some features of DAC instance. + */ +typedef struct +{ + uint32_t TriggerSource; /*!< Set the conversion trigger source for the selected DAC channel: internal (SW start) or from external peripheral (timer event, external interrupt line). + This parameter can be a value of @ref DAC_LL_EC_TRIGGER_SOURCE + + This feature can be modified afterwards using unitary function @ref LL_DAC_SetTriggerSource(). */ + + uint32_t WaveAutoGeneration; /*!< Set the waveform automatic generation mode for the selected DAC channel. + This parameter can be a value of @ref DAC_LL_EC_WAVE_AUTO_GENERATION_MODE + + This feature can be modified afterwards using unitary function @ref LL_DAC_SetWaveAutoGeneration(). */ + + uint32_t WaveAutoGenerationConfig; /*!< Set the waveform automatic generation mode for the selected DAC channel. + If waveform automatic generation mode is set to noise, this parameter can be a value of @ref DAC_LL_EC_WAVE_NOISE_LFSR_UNMASK_BITS + If waveform automatic generation mode is set to triangle, this parameter can be a value of @ref DAC_LL_EC_WAVE_TRIANGLE_AMPLITUDE + @note If waveform automatic generation mode is disabled, this parameter is discarded. + + This feature can be modified afterwards using unitary function @ref LL_DAC_SetWaveNoiseLFSR(), @ref LL_DAC_SetWaveTriangleAmplitude() + depending on the wave automatic generation selected. */ + + uint32_t OutputBuffer; /*!< Set the output buffer for the selected DAC channel. + This parameter can be a value of @ref DAC_LL_EC_OUTPUT_BUFFER + + This feature can be modified afterwards using unitary function @ref LL_DAC_SetOutputBuffer(). */ + + uint32_t OutputConnection; /*!< Set the output connection for the selected DAC channel. + This parameter can be a value of @ref DAC_LL_EC_OUTPUT_CONNECTION + + This feature can be modified afterwards using unitary function @ref LL_DAC_SetOutputConnection(). */ + + uint32_t OutputMode; /*!< Set the output mode normal or sample-and-hold for the selected DAC channel. + This parameter can be a value of @ref DAC_LL_EC_OUTPUT_MODE + + This feature can be modified afterwards using unitary function @ref LL_DAC_SetOutputMode(). */ +} LL_DAC_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DAC_LL_Exported_Constants DAC Exported Constants + * @{ + */ + +/** @defgroup DAC_LL_EC_GET_FLAG DAC flags + * @brief Flags defines which can be used with LL_DAC_ReadReg function + * @{ + */ +/* DAC channel 1 flags */ +#define LL_DAC_FLAG_DMAUDR1 (DAC_SR_DMAUDR1) /*!< DAC channel 1 flag DMA underrun */ +#define LL_DAC_FLAG_CAL1 (DAC_SR_CAL_FLAG1) /*!< DAC channel 1 flag offset calibration status */ +#define LL_DAC_FLAG_BWST1 (DAC_SR_BWST1) /*!< DAC channel 1 flag busy writing sample time */ + +#if defined(DAC_CHANNEL2_SUPPORT) +/* DAC channel 2 flags */ +#define LL_DAC_FLAG_DMAUDR2 (DAC_SR_DMAUDR2) /*!< DAC channel 2 flag DMA underrun */ +#define LL_DAC_FLAG_CAL2 (DAC_SR_CAL_FLAG2) /*!< DAC channel 2 flag offset calibration status */ +#define LL_DAC_FLAG_BWST2 (DAC_SR_BWST2) /*!< DAC channel 2 flag busy writing sample time */ +#endif /* DAC_CHANNEL2_SUPPORT */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_IT DAC interruptions + * @brief IT defines which can be used with LL_DAC_ReadReg and LL_DAC_WriteReg functions + * @{ + */ +#define LL_DAC_IT_DMAUDRIE1 (DAC_CR_DMAUDRIE1) /*!< DAC channel 1 interruption DMA underrun */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define LL_DAC_IT_DMAUDRIE2 (DAC_CR_DMAUDRIE2) /*!< DAC channel 2 interruption DMA underrun */ +#endif /* DAC_CHANNEL2_SUPPORT */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_CHANNEL DAC channels + * @{ + */ +#define LL_DAC_CHANNEL_1 (DAC_REG_SHSR1_REGOFFSET | DAC_REG_DOR1_REGOFFSET | DAC_REG_DHR12R1_REGOFFSET | DAC_REG_DHR12L1_REGOFFSET | DAC_REG_DHR8R1_REGOFFSET | DAC_CR_CH1_BITOFFSET | DAC_SWTR_CH1) /*!< DAC channel 1 */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define LL_DAC_CHANNEL_2 (DAC_REG_SHSR2_REGOFFSET | DAC_REG_DOR2_REGOFFSET | DAC_REG_DHR12R2_REGOFFSET | DAC_REG_DHR12L2_REGOFFSET | DAC_REG_DHR8R2_REGOFFSET | DAC_CR_CH2_BITOFFSET | DAC_SWTR_CH2) /*!< DAC channel 2 */ +#endif /* DAC_CHANNEL2_SUPPORT */ +/** + * @} + */ +#if defined (DAC_CR_HFSEL) /* High frequency interface mode */ + +/** @defgroup DAC_LL_EC_HIGH_FREQUENCY_MODE DAC high frequency interface mode + * @brief High frequency interface mode defines that can be used with LL_DAC_SetHighFrequencyMode and LL_DAC_GetHighFrequencyMode + * @{ + */ +#define LL_DAC_HIGH_FREQ_MODE_DISABLE 0x00000000U /*!< High frequency interface mode disabled */ +#define LL_DAC_HIGH_FREQ_MODE_ABOVE_80MHZ (DAC_CR_HFSEL) /*!< High frequency interface mode compatible to AHB>80MHz enabled */ +/** + * @} + */ +#endif /* High frequency interface mode */ + +/** @defgroup DAC_LL_EC_OPERATING_MODE DAC operating mode + * @{ + */ +#define LL_DAC_MODE_NORMAL_OPERATION 0x00000000U /*!< DAC channel in mode normal operation */ +#define LL_DAC_MODE_CALIBRATION (DAC_CR_CEN1) /*!< DAC channel in mode calibration */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_TRIGGER_SOURCE DAC trigger source + * @{ + */ +#if defined (DAC_CR_TSEL1_3) +#define LL_DAC_TRIG_EXT_TIM1_TRGO ( DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM1 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM2_TRGO ( DAC_CR_TSEL1_1 ) /*!< DAC channel conversion trigger from external IP: TIM2 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM4_TRGO ( DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM4 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM5_TRGO ( DAC_CR_TSEL1_2 ) /*!< DAC channel conversion trigger from external IP: TIM5 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM6_TRGO ( DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM6 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM7_TRGO ( DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 ) /*!< DAC channel conversion trigger from external IP: TIM7 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM8_TRGO ( DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM8 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM15_TRGO (DAC_CR_TSEL1_3 ) /*!< DAC channel conversion trigger from external IP: TIM15 TRGO. */ +#define LL_DAC_TRIG_EXT_LPTIM1_OUT (DAC_CR_TSEL1_3 | DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: LPTIM1 TRGO. */ +#define LL_DAC_TRIG_EXT_LPTIM2_OUT (DAC_CR_TSEL1_3 | DAC_CR_TSEL1_2 ) /*!< DAC channel conversion trigger from external IP: LPTIM2 TRGO. */ +#define LL_DAC_TRIG_EXT_EXTI_LINE9 (DAC_CR_TSEL1_3 | DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: external interrupt line 9. */ +#define LL_DAC_TRIG_SOFTWARE 0x00000000U /*!< DAC channel conversion trigger internal (SW start) */ +#else +#define LL_DAC_TRIG_SOFTWARE (DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger internal (SW start) */ +#define LL_DAC_TRIG_EXT_TIM2_TRGO (DAC_CR_TSEL1_2 ) /*!< DAC channel conversion trigger from external IP: TIM2 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM4_TRGO (DAC_CR_TSEL1_2 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM4 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM5_TRGO ( DAC_CR_TSEL1_1 | DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM5 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM6_TRGO 0x00000000U /*!< DAC channel conversion trigger from external IP: TIM6 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM7_TRGO ( DAC_CR_TSEL1_1 ) /*!< DAC channel conversion trigger from external IP: TIM7 TRGO. */ +#define LL_DAC_TRIG_EXT_TIM8_TRGO ( DAC_CR_TSEL1_0) /*!< DAC channel conversion trigger from external IP: TIM8 TRGO. */ +#define LL_DAC_TRIG_EXT_EXTI_LINE9 (DAC_CR_TSEL1_2 | DAC_CR_TSEL1_1 ) /*!< DAC channel conversion trigger from external IP: external interrupt line 9. */ +#endif + +/** + * @} + */ + +/** @defgroup DAC_LL_EC_WAVE_AUTO_GENERATION_MODE DAC waveform automatic generation mode + * @{ + */ +#define LL_DAC_WAVE_AUTO_GENERATION_NONE 0x00000000U /*!< DAC channel wave auto generation mode disabled. */ +#define LL_DAC_WAVE_AUTO_GENERATION_NOISE ( DAC_CR_WAVE1_0) /*!< DAC channel wave auto generation mode enabled, set generated noise waveform. */ +#define LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE (DAC_CR_WAVE1_1 ) /*!< DAC channel wave auto generation mode enabled, set generated triangle waveform. */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_WAVE_NOISE_LFSR_UNMASK_BITS DAC wave generation - Noise LFSR unmask bits + * @{ + */ +#define LL_DAC_NOISE_LFSR_UNMASK_BIT0 0x00000000U /*!< Noise wave generation, unmask LFSR bit0, for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS1_0 ( DAC_CR_MAMP1_0) /*!< Noise wave generation, unmask LFSR bits[1:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS2_0 ( DAC_CR_MAMP1_1 ) /*!< Noise wave generation, unmask LFSR bits[2:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS3_0 ( DAC_CR_MAMP1_1 | DAC_CR_MAMP1_0) /*!< Noise wave generation, unmask LFSR bits[3:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS4_0 ( DAC_CR_MAMP1_2 ) /*!< Noise wave generation, unmask LFSR bits[4:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS5_0 ( DAC_CR_MAMP1_2 | DAC_CR_MAMP1_0) /*!< Noise wave generation, unmask LFSR bits[5:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS6_0 ( DAC_CR_MAMP1_2 | DAC_CR_MAMP1_1 ) /*!< Noise wave generation, unmask LFSR bits[6:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS7_0 ( DAC_CR_MAMP1_2 | DAC_CR_MAMP1_1 | DAC_CR_MAMP1_0) /*!< Noise wave generation, unmask LFSR bits[7:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS8_0 (DAC_CR_MAMP1_3 ) /*!< Noise wave generation, unmask LFSR bits[8:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS9_0 (DAC_CR_MAMP1_3 | DAC_CR_MAMP1_0) /*!< Noise wave generation, unmask LFSR bits[9:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS10_0 (DAC_CR_MAMP1_3 | DAC_CR_MAMP1_1 ) /*!< Noise wave generation, unmask LFSR bits[10:0], for the selected DAC channel */ +#define LL_DAC_NOISE_LFSR_UNMASK_BITS11_0 (DAC_CR_MAMP1_3 | DAC_CR_MAMP1_1 | DAC_CR_MAMP1_0) /*!< Noise wave generation, unmask LFSR bits[11:0], for the selected DAC channel */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_WAVE_TRIANGLE_AMPLITUDE DAC wave generation - Triangle amplitude + * @{ + */ +#define LL_DAC_TRIANGLE_AMPLITUDE_1 0x00000000U /*!< Triangle wave generation, amplitude of 1 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_3 ( DAC_CR_MAMP1_0) /*!< Triangle wave generation, amplitude of 3 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_7 ( DAC_CR_MAMP1_1 ) /*!< Triangle wave generation, amplitude of 7 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_15 ( DAC_CR_MAMP1_1 | DAC_CR_MAMP1_0) /*!< Triangle wave generation, amplitude of 15 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_31 ( DAC_CR_MAMP1_2 ) /*!< Triangle wave generation, amplitude of 31 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_63 ( DAC_CR_MAMP1_2 | DAC_CR_MAMP1_0) /*!< Triangle wave generation, amplitude of 63 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_127 ( DAC_CR_MAMP1_2 | DAC_CR_MAMP1_1 ) /*!< Triangle wave generation, amplitude of 127 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_255 ( DAC_CR_MAMP1_2 | DAC_CR_MAMP1_1 | DAC_CR_MAMP1_0) /*!< Triangle wave generation, amplitude of 255 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_511 (DAC_CR_MAMP1_3 ) /*!< Triangle wave generation, amplitude of 512 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_1023 (DAC_CR_MAMP1_3 | DAC_CR_MAMP1_0) /*!< Triangle wave generation, amplitude of 1023 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_2047 (DAC_CR_MAMP1_3 | DAC_CR_MAMP1_1 ) /*!< Triangle wave generation, amplitude of 2047 LSB of DAC output range, for the selected DAC channel */ +#define LL_DAC_TRIANGLE_AMPLITUDE_4095 (DAC_CR_MAMP1_3 | DAC_CR_MAMP1_1 | DAC_CR_MAMP1_0) /*!< Triangle wave generation, amplitude of 4095 LSB of DAC output range, for the selected DAC channel */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_OUTPUT_MODE DAC channel output mode + * @{ + */ +#define LL_DAC_OUTPUT_MODE_NORMAL 0x00000000U /*!< The selected DAC channel output is on mode normal. */ +#define LL_DAC_OUTPUT_MODE_SAMPLE_AND_HOLD (DAC_MCR_MODE1_2) /*!< The selected DAC channel output is on mode sample-and-hold. Mode sample-and-hold requires an external capacitor, refer to description of function @ref LL_DAC_ConfigOutput() or @ref LL_DAC_SetOutputMode(). */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_OUTPUT_BUFFER DAC channel output buffer + * @{ + */ +#define LL_DAC_OUTPUT_BUFFER_ENABLE 0x00000000U /*!< The selected DAC channel output is buffered: higher drive current capability, but also higher current consumption */ +#define LL_DAC_OUTPUT_BUFFER_DISABLE (DAC_MCR_MODE1_1) /*!< The selected DAC channel output is not buffered: lower drive current capability, but also lower current consumption */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_OUTPUT_CONNECTION DAC channel output connection + * @{ + */ +#define LL_DAC_OUTPUT_CONNECT_GPIO 0x00000000U /*!< The selected DAC channel output is connected to external pin */ +#define LL_DAC_OUTPUT_CONNECT_INTERNAL (DAC_MCR_MODE1_0) /*!< The selected DAC channel output is connected to on-chip peripherals via internal paths. On this STM32 series, output connection depends on output mode (normal or sample and hold) and output buffer state. Refer to comments of function @ref LL_DAC_SetOutputConnection(). */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_RESOLUTION DAC channel output resolution + * @{ + */ +#define LL_DAC_RESOLUTION_12B 0x00000000U /*!< DAC channel resolution 12 bits */ +#define LL_DAC_RESOLUTION_8B 0x00000002U /*!< DAC channel resolution 8 bits */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_REGISTERS DAC registers compliant with specific purpose + * @{ + */ +/* List of DAC registers intended to be used (most commonly) with */ +/* DMA transfer. */ +/* Refer to function @ref LL_DAC_DMA_GetRegAddr(). */ +#define LL_DAC_DMA_REG_DATA_12BITS_RIGHT_ALIGNED DAC_REG_DHR12RX_REGOFFSET_BITOFFSET_POS /*!< DAC channel data holding register 12 bits right aligned */ +#define LL_DAC_DMA_REG_DATA_12BITS_LEFT_ALIGNED DAC_REG_DHR12LX_REGOFFSET_BITOFFSET_POS /*!< DAC channel data holding register 12 bits left aligned */ +#define LL_DAC_DMA_REG_DATA_8BITS_RIGHT_ALIGNED DAC_REG_DHR8RX_REGOFFSET_BITOFFSET_POS /*!< DAC channel data holding register 8 bits right aligned */ +/** + * @} + */ + +/** @defgroup DAC_LL_EC_HW_DELAYS Definitions of DAC hardware constraints delays + * @note Only DAC peripheral HW delays are defined in DAC LL driver driver, + * not timeout values. + * For details on delays values, refer to descriptions in source code + * above each literal definition. + * @{ + */ + +/* Delay for DAC channel voltage settling time from DAC channel startup */ +/* (transition from disable to enable). */ +/* Note: DAC channel startup time depends on board application environment: */ +/* impedance connected to DAC channel output. */ +/* The delay below is specified under conditions: */ +/* - voltage maximum transition (lowest to highest value) */ +/* - until voltage reaches final value +-1LSB */ +/* - DAC channel output buffer enabled */ +/* - load impedance of 5kOhm (min), 50pF (max) */ +/* Literal set to maximum value (refer to device datasheet, */ +/* parameter "tWAKEUP"). */ +/* Unit: us */ +#define LL_DAC_DELAY_STARTUP_VOLTAGE_SETTLING_US 8U /*!< Delay for DAC channel voltage settling time from DAC channel startup (transition from disable to enable) */ + + +/* Delay for DAC channel voltage settling time. */ +/* Note: DAC channel startup time depends on board application environment: */ +/* impedance connected to DAC channel output. */ +/* The delay below is specified under conditions: */ +/* - voltage maximum transition (lowest to highest value) */ +/* - until voltage reaches final value +-1LSB */ +/* - DAC channel output buffer enabled */ +/* - load impedance of 5kOhm min, 50pF max */ +/* Literal set to maximum value (refer to device datasheet, */ +/* parameter "tSETTLING"). */ +/* Unit: us */ +#define LL_DAC_DELAY_VOLTAGE_SETTLING_US 3U /*!< Delay for DAC channel voltage settling time */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup DAC_LL_Exported_Macros DAC Exported Macros + * @{ + */ + +/** @defgroup DAC_LL_EM_WRITE_READ Common write and read registers macros + * @{ + */ + +/** + * @brief Write a value in DAC register + * @param __INSTANCE__ DAC Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_DAC_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in DAC register + * @param __INSTANCE__ DAC Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_DAC_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) + +/** + * @} + */ + +/** @defgroup DAC_LL_EM_HELPER_MACRO DAC helper macro + * @{ + */ + +/** + * @brief Helper macro to get DAC channel number in decimal format + * from literals LL_DAC_CHANNEL_x. + * Example: + * __LL_DAC_CHANNEL_TO_DECIMAL_NB(LL_DAC_CHANNEL_1) + * will return decimal number "1". + * @note The input can be a value from functions where a channel + * number is returned. + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_DAC_CHANNEL_1 + * @arg @ref LL_DAC_CHANNEL_2 + * @retval 1...2 + */ +#define __LL_DAC_CHANNEL_TO_DECIMAL_NB(__CHANNEL__) \ + ((__CHANNEL__) & DAC_SWTR_CHX_MASK) + +/** + * @brief Helper macro to get DAC channel in literal format LL_DAC_CHANNEL_x + * from number in decimal format. + * Example: + * __LL_DAC_DECIMAL_NB_TO_CHANNEL(1) + * will return a data equivalent to "LL_DAC_CHANNEL_1". + * @note If the input parameter does not correspond to a DAC channel, + * this macro returns value '0'. + * @param __DECIMAL_NB__ 1...2 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_CHANNEL_1 + * @arg @ref LL_DAC_CHANNEL_2 + */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define __LL_DAC_DECIMAL_NB_TO_CHANNEL(__DECIMAL_NB__) \ + (((__DECIMAL_NB__) == 1U) \ + ? ( \ + LL_DAC_CHANNEL_1 \ + ) \ + : \ + (((__DECIMAL_NB__) == 2U) \ + ? ( \ + LL_DAC_CHANNEL_2 \ + ) \ + : \ + ( \ + 0U \ + ) \ + ) \ + ) +#else +#define __LL_DAC_DECIMAL_NB_TO_CHANNEL(__DECIMAL_NB__) \ + (((__DECIMAL_NB__) == 1U) \ + ? ( \ + LL_DAC_CHANNEL_1 \ + ) \ + : \ + ( \ + 0U \ + ) \ + ) +#endif /* DAC_CHANNEL2_SUPPORT */ + +/** + * @brief Helper macro to define the DAC conversion data full-scale digital + * value corresponding to the selected DAC resolution. + * @note DAC conversion data full-scale corresponds to voltage range + * determined by analog voltage references Vref+ and Vref- + * (refer to reference manual). + * @param __DAC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_DAC_RESOLUTION_12B + * @arg @ref LL_DAC_RESOLUTION_8B + * @retval ADC conversion data equivalent voltage value (unit: mVolt) + */ +#define __LL_DAC_DIGITAL_SCALE(__DAC_RESOLUTION__) \ + ((0x00000FFFU) >> ((__DAC_RESOLUTION__) << 1U)) + +/** + * @brief Helper macro to calculate the DAC conversion data (unit: digital + * value) corresponding to a voltage (unit: mVolt). + * @note This helper macro is intended to provide input data in voltage + * rather than digital value, + * to be used with LL DAC functions such as + * @ref LL_DAC_ConvertData12RightAligned(). + * @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 __DAC_VOLTAGE__ Voltage to be generated by DAC channel + * (unit: mVolt). + * @param __DAC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_DAC_RESOLUTION_12B + * @arg @ref LL_DAC_RESOLUTION_8B + * @retval DAC conversion data (unit: digital value) + */ +#define __LL_DAC_CALC_VOLTAGE_TO_DATA(__VREFANALOG_VOLTAGE__,\ + __DAC_VOLTAGE__,\ + __DAC_RESOLUTION__) \ + ((__DAC_VOLTAGE__) * __LL_DAC_DIGITAL_SCALE(__DAC_RESOLUTION__) \ + / (__VREFANALOG_VOLTAGE__) \ + ) + +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DAC_LL_Exported_Functions DAC Exported Functions + * @{ + */ + +#if defined (DAC_CR_HFSEL) /* High frequency interface mode */ + +/** @defgroup DAC_LL_EF_High_Frequency_Configuration High Frequency Configuration of DAC instance + * @{ + */ +/** + * @brief Set the high frequency interface mode for the selected DAC instance + * @rmtoll CR HFSEL LL_DAC_SetHighFrequencyMode + * @param DACx DAC instance + * @param HighFreqMode This parameter can be one of the following values: + * @arg @ref LL_DAC_HIGH_FREQ_MODE_DISABLE + * @arg @ref LL_DAC_HIGH_FREQ_MODE_ABOVE_80MHZ + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetHighFrequencyMode(DAC_TypeDef *DACx, uint32_t HighFreqMode) +{ + MODIFY_REG(DACx->CR, DAC_CR_HFSEL, HighFreqMode); +} + +/** + * @brief Get the high frequency interface mode for the selected DAC instance + * @rmtoll CR HFSEL LL_DAC_GetHighFrequencyMode + * @param DACx DAC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_HIGH_FREQ_MODE_DISABLE + * @arg @ref LL_DAC_HIGH_FREQ_MODE_ABOVE_80MHZ + */ +__STATIC_INLINE uint32_t LL_DAC_GetHighFrequencyMode(DAC_TypeDef *DACx) +{ + return (uint32_t)(READ_BIT(DACx->CR, DAC_CR_HFSEL)); +} +/** + * @} + */ + +#endif /* High frequency interface mode */ + +/** @defgroup DAC_LL_EF_Configuration Configuration of DAC channels + * @{ + */ + +/** + * @brief Set the operating mode for the selected DAC channel: + * calibration or normal operating mode. + * @rmtoll CR CEN1 LL_DAC_SetMode\n + * CR CEN2 LL_DAC_SetMode + * @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 + * @param ChannelMode This parameter can be one of the following values: + * @arg @ref LL_DAC_MODE_NORMAL_OPERATION + * @arg @ref LL_DAC_MODE_CALIBRATION + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetMode(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t ChannelMode) +{ + MODIFY_REG(DACx->CR, + DAC_CR_CEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + ChannelMode << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the operating mode for the selected DAC channel: + * calibration or normal operating mode. + * @rmtoll CR CEN1 LL_DAC_GetMode\n + * CR CEN2 LL_DAC_GetMode + * @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 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_MODE_NORMAL_OPERATION + * @arg @ref LL_DAC_MODE_CALIBRATION + */ +__STATIC_INLINE uint32_t LL_DAC_GetMode(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->CR, DAC_CR_CEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the offset trimming value for the selected DAC channel. + * Trimming has an impact when output buffer is enabled + * and is intended to replace factory calibration default values. + * @rmtoll CCR OTRIM1 LL_DAC_SetTrimmingValue\n + * CCR OTRIM2 LL_DAC_SetTrimmingValue + * @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 + * @param TrimmingValue Value between Min_Data=0x00 and Max_Data=0x1F + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetTrimmingValue(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t TrimmingValue) +{ + MODIFY_REG(DACx->CCR, + DAC_CCR_OTRIM1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + TrimmingValue << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the offset trimming value for the selected DAC channel. + * Trimming has an impact when output buffer is enabled + * and is intended to replace factory calibration default values. + * @rmtoll CCR OTRIM1 LL_DAC_GetTrimmingValue\n + * CCR OTRIM2 LL_DAC_GetTrimmingValue + * @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 + * @retval TrimmingValue Value between Min_Data=0x00 and Max_Data=0x1F + */ +__STATIC_INLINE uint32_t LL_DAC_GetTrimmingValue(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->CCR, DAC_CCR_OTRIM1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the conversion trigger source for the selected DAC channel. + * @note For conversion trigger source to be effective, DAC trigger + * must be enabled using function @ref LL_DAC_EnableTrigger(). + * @note To set conversion trigger source, DAC channel must be disabled. + * Otherwise, the setting is discarded. + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @rmtoll CR TSEL1 LL_DAC_SetTriggerSource\n + * CR TSEL2 LL_DAC_SetTriggerSource + * @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 + * @param TriggerSource This parameter can be one of the following values: + * @arg @ref LL_DAC_TRIG_SOFTWARE + * @arg @ref LL_DAC_TRIG_EXT_TIM1_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM5_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM7_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM15_TRGO + * @arg @ref LL_DAC_TRIG_EXT_LPTIM1_OUT + * @arg @ref LL_DAC_TRIG_EXT_LPTIM2_OUT + * @arg @ref LL_DAC_TRIG_EXT_EXTI_LINE9 + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetTriggerSource(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t TriggerSource) +{ + MODIFY_REG(DACx->CR, + DAC_CR_TSEL1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + TriggerSource << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the conversion trigger source for the selected DAC channel. + * @note For conversion trigger source to be effective, DAC trigger + * must be enabled using function @ref LL_DAC_EnableTrigger(). + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @rmtoll CR TSEL1 LL_DAC_GetTriggerSource\n + * CR TSEL2 LL_DAC_GetTriggerSource + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_TRIG_SOFTWARE + * @arg @ref LL_DAC_TRIG_EXT_TIM1_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM5_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM6_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM7_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_DAC_TRIG_EXT_TIM15_TRGO + * @arg @ref LL_DAC_TRIG_EXT_LPTIM1_OUT + * @arg @ref LL_DAC_TRIG_EXT_LPTIM2_OUT + * @arg @ref LL_DAC_TRIG_EXT_EXTI_LINE9 + */ +__STATIC_INLINE uint32_t LL_DAC_GetTriggerSource(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->CR, DAC_CR_TSEL1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the waveform automatic generation mode + * for the selected DAC channel. + * @rmtoll CR WAVE1 LL_DAC_SetWaveAutoGeneration\n + * CR WAVE2 LL_DAC_SetWaveAutoGeneration + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param WaveAutoGeneration This parameter can be one of the following values: + * @arg @ref LL_DAC_WAVE_AUTO_GENERATION_NONE + * @arg @ref LL_DAC_WAVE_AUTO_GENERATION_NOISE + * @arg @ref LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetWaveAutoGeneration(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t WaveAutoGeneration) +{ + MODIFY_REG(DACx->CR, + DAC_CR_WAVE1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + WaveAutoGeneration << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the waveform automatic generation mode + * for the selected DAC channel. + * @rmtoll CR WAVE1 LL_DAC_GetWaveAutoGeneration\n + * CR WAVE2 LL_DAC_GetWaveAutoGeneration + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_WAVE_AUTO_GENERATION_NONE + * @arg @ref LL_DAC_WAVE_AUTO_GENERATION_NOISE + * @arg @ref LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE + */ +__STATIC_INLINE uint32_t LL_DAC_GetWaveAutoGeneration(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->CR, DAC_CR_WAVE1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the noise waveform generation for the selected DAC channel: + * Noise mode and parameters LFSR (linear feedback shift register). + * @note For wave generation to be effective, DAC channel + * wave generation mode must be enabled using + * function @ref LL_DAC_SetWaveAutoGeneration(). + * @note This setting can be set when the selected DAC channel is disabled + * (otherwise, the setting operation is ignored). + * @rmtoll CR MAMP1 LL_DAC_SetWaveNoiseLFSR\n + * CR MAMP2 LL_DAC_SetWaveNoiseLFSR + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param NoiseLFSRMask This parameter can be one of the following values: + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BIT0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS1_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS2_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS3_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS4_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS5_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS6_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS7_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS8_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS9_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS10_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS11_0 + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetWaveNoiseLFSR(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t NoiseLFSRMask) +{ + MODIFY_REG(DACx->CR, + DAC_CR_MAMP1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + NoiseLFSRMask << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the noise waveform generation for the selected DAC channel: + * Noise mode and parameters LFSR (linear feedback shift register). + * @rmtoll CR MAMP1 LL_DAC_GetWaveNoiseLFSR\n + * CR MAMP2 LL_DAC_GetWaveNoiseLFSR + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BIT0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS1_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS2_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS3_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS4_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS5_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS6_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS7_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS8_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS9_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS10_0 + * @arg @ref LL_DAC_NOISE_LFSR_UNMASK_BITS11_0 + */ +__STATIC_INLINE uint32_t LL_DAC_GetWaveNoiseLFSR(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->CR, DAC_CR_MAMP1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the triangle waveform generation for the selected DAC channel: + * triangle mode and amplitude. + * @note For wave generation to be effective, DAC channel + * wave generation mode must be enabled using + * function @ref LL_DAC_SetWaveAutoGeneration(). + * @note This setting can be set when the selected DAC channel is disabled + * (otherwise, the setting operation is ignored). + * @rmtoll CR MAMP1 LL_DAC_SetWaveTriangleAmplitude\n + * CR MAMP2 LL_DAC_SetWaveTriangleAmplitude + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param TriangleAmplitude This parameter can be one of the following values: + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_1 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_3 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_7 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_15 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_31 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_63 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_127 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_255 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_511 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_1023 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_2047 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_4095 + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetWaveTriangleAmplitude(DAC_TypeDef *DACx, uint32_t DAC_Channel, + uint32_t TriangleAmplitude) +{ + MODIFY_REG(DACx->CR, + DAC_CR_MAMP1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + TriangleAmplitude << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the triangle waveform generation for the selected DAC channel: + * triangle mode and amplitude. + * @rmtoll CR MAMP1 LL_DAC_GetWaveTriangleAmplitude\n + * CR MAMP2 LL_DAC_GetWaveTriangleAmplitude + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_1 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_3 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_7 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_15 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_31 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_63 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_127 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_255 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_511 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_1023 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_2047 + * @arg @ref LL_DAC_TRIANGLE_AMPLITUDE_4095 + */ +__STATIC_INLINE uint32_t LL_DAC_GetWaveTriangleAmplitude(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->CR, DAC_CR_MAMP1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the output for the selected DAC channel. + * @note This function set several features: + * - mode normal or sample-and-hold + * - buffer + * - connection to GPIO or internal path. + * These features can also be set individually using + * dedicated functions: + * - @ref LL_DAC_SetOutputBuffer() + * - @ref LL_DAC_SetOutputMode() + * - @ref LL_DAC_SetOutputConnection() + * @note On this STM32 series, output connection depends on output mode + * (normal or sample and hold) and output buffer state. + * - if output connection is set to internal path and output buffer + * is enabled (whatever output mode): + * output connection is also connected to GPIO pin + * (both connections to GPIO pin and internal path). + * - if output connection is set to GPIO pin, output buffer + * is disabled, output mode set to sample and hold: + * output connection is also connected to internal path + * (both connections to GPIO pin and internal path). + * @note Mode sample-and-hold requires an external capacitor + * to be connected between DAC channel output and ground. + * Capacitor value depends on load on DAC channel output and + * sample-and-hold timings configured. + * As indication, capacitor typical value is 100nF + * (refer to device datasheet, parameter "CSH"). + * @rmtoll CR MODE1 LL_DAC_ConfigOutput\n + * CR MODE2 LL_DAC_ConfigOutput + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param OutputMode This parameter can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_MODE_NORMAL + * @arg @ref LL_DAC_OUTPUT_MODE_SAMPLE_AND_HOLD + * @param OutputBuffer This parameter can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_BUFFER_ENABLE + * @arg @ref LL_DAC_OUTPUT_BUFFER_DISABLE + * @param OutputConnection This parameter can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_CONNECT_GPIO + * @arg @ref LL_DAC_OUTPUT_CONNECT_INTERNAL + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConfigOutput(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t OutputMode, + uint32_t OutputBuffer, uint32_t OutputConnection) +{ + MODIFY_REG(DACx->MCR, + (DAC_MCR_MODE1_2 | DAC_MCR_MODE1_1 | DAC_MCR_MODE1_0) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + (OutputMode | OutputBuffer | OutputConnection) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Set the output mode normal or sample-and-hold + * for the selected DAC channel. + * @note Mode sample-and-hold requires an external capacitor + * to be connected between DAC channel output and ground. + * Capacitor value depends on load on DAC channel output and + * sample-and-hold timings configured. + * As indication, capacitor typical value is 100nF + * (refer to device datasheet, parameter "CSH"). + * @rmtoll CR MODE1 LL_DAC_SetOutputMode\n + * CR MODE2 LL_DAC_SetOutputMode + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param OutputMode This parameter can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_MODE_NORMAL + * @arg @ref LL_DAC_OUTPUT_MODE_SAMPLE_AND_HOLD + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetOutputMode(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t OutputMode) +{ + MODIFY_REG(DACx->MCR, + (uint32_t)DAC_MCR_MODE1_2 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + OutputMode << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the output mode normal or sample-and-hold for the selected DAC channel. + * @rmtoll CR MODE1 LL_DAC_GetOutputMode\n + * CR MODE2 LL_DAC_GetOutputMode + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_MODE_NORMAL + * @arg @ref LL_DAC_OUTPUT_MODE_SAMPLE_AND_HOLD + */ +__STATIC_INLINE uint32_t LL_DAC_GetOutputMode(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->MCR, (uint32_t)DAC_MCR_MODE1_2 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the output buffer for the selected DAC channel. + * @note On this STM32 series, when buffer is enabled, its offset can be + * trimmed: factory calibration default values can be + * replaced by user trimming values, using function + * @ref LL_DAC_SetTrimmingValue(). + * @rmtoll CR MODE1 LL_DAC_SetOutputBuffer\n + * CR MODE2 LL_DAC_SetOutputBuffer + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param OutputBuffer This parameter can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_BUFFER_ENABLE + * @arg @ref LL_DAC_OUTPUT_BUFFER_DISABLE + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetOutputBuffer(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t OutputBuffer) +{ + MODIFY_REG(DACx->MCR, + (uint32_t)DAC_MCR_MODE1_1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + OutputBuffer << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the output buffer state for the selected DAC channel. + * @rmtoll CR MODE1 LL_DAC_GetOutputBuffer\n + * CR MODE2 LL_DAC_GetOutputBuffer + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_BUFFER_ENABLE + * @arg @ref LL_DAC_OUTPUT_BUFFER_DISABLE + */ +__STATIC_INLINE uint32_t LL_DAC_GetOutputBuffer(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->MCR, (uint32_t)DAC_MCR_MODE1_1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the output connection for the selected DAC channel. + * @note On this STM32 series, output connection depends on output mode (normal or + * sample and hold) and output buffer state. + * - if output connection is set to internal path and output buffer + * is enabled (whatever output mode): + * output connection is also connected to GPIO pin + * (both connections to GPIO pin and internal path). + * - if output connection is set to GPIO pin, output buffer + * is disabled, output mode set to sample and hold: + * output connection is also connected to internal path + * (both connections to GPIO pin and internal path). + * @rmtoll CR MODE1 LL_DAC_SetOutputConnection\n + * CR MODE2 LL_DAC_SetOutputConnection + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param OutputConnection This parameter can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_CONNECT_GPIO + * @arg @ref LL_DAC_OUTPUT_CONNECT_INTERNAL + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetOutputConnection(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t OutputConnection) +{ + MODIFY_REG(DACx->MCR, + (uint32_t)DAC_MCR_MODE1_0 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + OutputConnection << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the output connection for the selected DAC channel. + * @note On this STM32 series, output connection depends on output mode (normal or + * sample and hold) and output buffer state. + * - if output connection is set to internal path and output buffer + * is enabled (whatever output mode): + * output connection is also connected to GPIO pin + * (both connections to GPIO pin and internal path). + * - if output connection is set to GPIO pin, output buffer + * is disabled, output mode set to sample and hold: + * output connection is also connected to internal path + * (both connections to GPIO pin and internal path). + * @rmtoll CR MODE1 LL_DAC_GetOutputConnection\n + * CR MODE2 LL_DAC_GetOutputConnection + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Returned value can be one of the following values: + * @arg @ref LL_DAC_OUTPUT_CONNECT_GPIO + * @arg @ref LL_DAC_OUTPUT_CONNECT_INTERNAL + */ +__STATIC_INLINE uint32_t LL_DAC_GetOutputConnection(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->MCR, (uint32_t)DAC_MCR_MODE1_0 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the sample-and-hold timing for the selected DAC channel: + * sample time + * @note Sample time must be set when DAC channel is disabled + * or during DAC operation when DAC channel flag BWSTx is reset, + * otherwise the setting is ignored. + * Check BWSTx flag state using function "LL_DAC_IsActiveFlag_BWSTx()". + * @rmtoll SHSR1 TSAMPLE1 LL_DAC_SetSampleAndHoldSampleTime\n + * SHSR2 TSAMPLE2 LL_DAC_SetSampleAndHoldSampleTime + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param SampleTime Value between Min_Data=0x000 and Max_Data=0x3FF + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetSampleAndHoldSampleTime(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t SampleTime) +{ + __IO uint32_t *preg = __DAC_PTR_REG_OFFSET(DACx->SHSR1, (DAC_Channel >> DAC_REG_SHSRX_REGOFFSET_BITOFFSET_POS) & DAC_REG_SHSRX_REGOFFSET_MASK_POSBIT0); + + MODIFY_REG(*preg, + DAC_SHSR1_TSAMPLE1, + SampleTime); +} + +/** + * @brief Get the sample-and-hold timing for the selected DAC channel: + * sample time + * @rmtoll SHSR1 TSAMPLE1 LL_DAC_GetSampleAndHoldSampleTime\n + * SHSR2 TSAMPLE2 LL_DAC_GetSampleAndHoldSampleTime + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Value between Min_Data=0x000 and Max_Data=0x3FF + */ +__STATIC_INLINE uint32_t LL_DAC_GetSampleAndHoldSampleTime(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + __IO uint32_t const *preg = __DAC_PTR_REG_OFFSET(DACx->SHSR1, (DAC_Channel >> DAC_REG_SHSRX_REGOFFSET_BITOFFSET_POS) & DAC_REG_SHSRX_REGOFFSET_MASK_POSBIT0); + + return (uint32_t) READ_BIT(*preg, DAC_SHSR1_TSAMPLE1); +} + +/** + * @brief Set the sample-and-hold timing for the selected DAC channel: + * hold time + * @rmtoll SHHR THOLD1 LL_DAC_SetSampleAndHoldHoldTime\n + * SHHR THOLD2 LL_DAC_SetSampleAndHoldHoldTime + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param HoldTime Value between Min_Data=0x000 and Max_Data=0x3FF + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetSampleAndHoldHoldTime(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t HoldTime) +{ + MODIFY_REG(DACx->SHHR, + DAC_SHHR_THOLD1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + HoldTime << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the sample-and-hold timing for the selected DAC channel: + * hold time + * @rmtoll SHHR THOLD1 LL_DAC_GetSampleAndHoldHoldTime\n + * SHHR THOLD2 LL_DAC_GetSampleAndHoldHoldTime + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Value between Min_Data=0x000 and Max_Data=0x3FF + */ +__STATIC_INLINE uint32_t LL_DAC_GetSampleAndHoldHoldTime(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->SHHR, DAC_SHHR_THOLD1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @brief Set the sample-and-hold timing for the selected DAC channel: + * refresh time + * @rmtoll SHRR TREFRESH1 LL_DAC_SetSampleAndHoldRefreshTime\n + * SHRR TREFRESH2 LL_DAC_SetSampleAndHoldRefreshTime + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param RefreshTime Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_SetSampleAndHoldRefreshTime(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t RefreshTime) +{ + MODIFY_REG(DACx->SHRR, + DAC_SHRR_TREFRESH1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK), + RefreshTime << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get the sample-and-hold timing for the selected DAC channel: + * refresh time + * @rmtoll SHRR TREFRESH1 LL_DAC_GetSampleAndHoldRefreshTime\n + * SHRR TREFRESH2 LL_DAC_GetSampleAndHoldRefreshTime + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DAC_GetSampleAndHoldRefreshTime(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return (uint32_t)(READ_BIT(DACx->SHRR, DAC_SHRR_TREFRESH1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + >> (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); +} + +/** + * @} + */ + +/** @defgroup DAC_LL_EF_DMA_Management DMA Management + * @{ + */ + +/** + * @brief Enable DAC DMA transfer request of the selected channel. + * @note To configure DMA source address (peripheral address), + * use function @ref LL_DAC_DMA_GetRegAddr(). + * @rmtoll CR DMAEN1 LL_DAC_EnableDMAReq\n + * CR DMAEN2 LL_DAC_EnableDMAReq + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_EnableDMAReq(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + SET_BIT(DACx->CR, + DAC_CR_DMAEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Disable DAC DMA transfer request of the selected channel. + * @note To configure DMA source address (peripheral address), + * use function @ref LL_DAC_DMA_GetRegAddr(). + * @rmtoll CR DMAEN1 LL_DAC_DisableDMAReq\n + * CR DMAEN2 LL_DAC_DisableDMAReq + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_DisableDMAReq(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + CLEAR_BIT(DACx->CR, + DAC_CR_DMAEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get DAC DMA transfer request state of the selected channel. + * (0: DAC DMA transfer request is disabled, 1: DAC DMA transfer request is enabled) + * @rmtoll CR DMAEN1 LL_DAC_IsDMAReqEnabled\n + * CR DMAEN2 LL_DAC_IsDMAReqEnabled + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsDMAReqEnabled(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return ((READ_BIT(DACx->CR, + DAC_CR_DMAEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + == (DAC_CR_DMAEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK))) ? 1UL : 0UL); +} + +/** + * @brief Function to help to configure DMA transfer to DAC: retrieve the + * DAC register address from DAC instance and a list of DAC registers + * intended to be used (most commonly) with DMA transfer. + * @note These DAC registers are data holding registers: + * when DAC conversion is requested, DAC generates a DMA transfer + * request to have data available in DAC data holding registers. + * @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, + * (uint32_t)&< array or variable >, + * LL_DAC_DMA_GetRegAddr(DAC1, LL_DAC_CHANNEL_1, LL_DAC_DMA_REG_DATA_12BITS_RIGHT_ALIGNED), + * LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + * @rmtoll DHR12R1 DACC1DHR LL_DAC_DMA_GetRegAddr\n + * DHR12L1 DACC1DHR LL_DAC_DMA_GetRegAddr\n + * DHR8R1 DACC1DHR LL_DAC_DMA_GetRegAddr\n + * DHR12R2 DACC2DHR LL_DAC_DMA_GetRegAddr\n + * DHR12L2 DACC2DHR LL_DAC_DMA_GetRegAddr\n + * DHR8R2 DACC2DHR LL_DAC_DMA_GetRegAddr + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param Register This parameter can be one of the following values: + * @arg @ref LL_DAC_DMA_REG_DATA_12BITS_RIGHT_ALIGNED + * @arg @ref LL_DAC_DMA_REG_DATA_12BITS_LEFT_ALIGNED + * @arg @ref LL_DAC_DMA_REG_DATA_8BITS_RIGHT_ALIGNED + * @retval DAC register address + */ +__STATIC_INLINE uint32_t LL_DAC_DMA_GetRegAddr(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t Register) +{ + /* Retrieve address of register DHR12Rx, DHR12Lx or DHR8Rx depending on */ + /* DAC channel selected. */ + return ((uint32_t)(__DAC_PTR_REG_OFFSET((DACx)->DHR12R1, + ((DAC_Channel >> (Register & 0x1FUL)) & DAC_REG_DHR_REGOFFSET_MASK_POSBIT0)))); +} +/** + * @} + */ + +/** @defgroup DAC_LL_EF_Operation Operation on DAC channels + * @{ + */ + +/** + * @brief Enable DAC selected channel. + * @rmtoll CR EN1 LL_DAC_Enable\n + * CR EN2 LL_DAC_Enable + * @note After enable from off state, DAC channel requires a delay + * for output voltage to reach accuracy +/- 1 LSB. + * Refer to device datasheet, parameter "tWAKEUP". + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_Enable(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + SET_BIT(DACx->CR, + DAC_CR_EN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Disable DAC selected channel. + * @rmtoll CR EN1 LL_DAC_Disable\n + * CR EN2 LL_DAC_Disable + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_Disable(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + CLEAR_BIT(DACx->CR, + DAC_CR_EN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get DAC enable state of the selected channel. + * (0: DAC channel is disabled, 1: DAC channel is enabled) + * @rmtoll CR EN1 LL_DAC_IsEnabled\n + * CR EN2 LL_DAC_IsEnabled + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsEnabled(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return ((READ_BIT(DACx->CR, + DAC_CR_EN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + == (DAC_CR_EN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK))) ? 1UL : 0UL); +} + +/** + * @brief Enable DAC trigger of the selected channel. + * @note - If DAC trigger is disabled, DAC conversion is performed + * automatically once the data holding register is updated, + * using functions "LL_DAC_ConvertData{8; 12}{Right; Left} Aligned()": + * @ref LL_DAC_ConvertData12RightAligned(), ... + * - If DAC trigger is enabled, DAC conversion is performed + * only when a hardware of software trigger event is occurring. + * Select trigger source using + * function @ref LL_DAC_SetTriggerSource(). + * @rmtoll CR TEN1 LL_DAC_EnableTrigger\n + * CR TEN2 LL_DAC_EnableTrigger + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_EnableTrigger(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + SET_BIT(DACx->CR, + DAC_CR_TEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Disable DAC trigger of the selected channel. + * @rmtoll CR TEN1 LL_DAC_DisableTrigger\n + * CR TEN2 LL_DAC_DisableTrigger + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_DisableTrigger(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + CLEAR_BIT(DACx->CR, + DAC_CR_TEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)); +} + +/** + * @brief Get DAC trigger state of the selected channel. + * (0: DAC trigger is disabled, 1: DAC trigger is enabled) + * @rmtoll CR TEN1 LL_DAC_IsTriggerEnabled\n + * CR TEN2 LL_DAC_IsTriggerEnabled + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsTriggerEnabled(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + return ((READ_BIT(DACx->CR, + DAC_CR_TEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)) + == (DAC_CR_TEN1 << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK))) ? 1UL : 0UL); +} + +/** + * @brief Trig DAC conversion by software for the selected DAC channel. + * @note Preliminarily, DAC trigger must be set to software trigger + * using function + * @ref LL_DAC_Init() + * @ref LL_DAC_SetTriggerSource() + * with parameter "LL_DAC_TRIGGER_SOFTWARE". + * and DAC trigger must be enabled using + * function @ref LL_DAC_EnableTrigger(). + * @note For devices featuring DAC with 2 channels: this function + * can perform a SW start of both DAC channels simultaneously. + * Two channels can be selected as parameter. + * Example: (LL_DAC_CHANNEL_1 | LL_DAC_CHANNEL_2) + * @rmtoll SWTRIGR SWTRIG1 LL_DAC_TrigSWConversion\n + * SWTRIGR SWTRIG2 LL_DAC_TrigSWConversion + * @param DACx DAC instance + * @param DAC_Channel This parameter can a combination of the following values: + * @arg @ref LL_DAC_CHANNEL_1 + * @arg @ref LL_DAC_CHANNEL_2 (1) + * + * (1) On this STM32 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval None + */ +__STATIC_INLINE void LL_DAC_TrigSWConversion(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + SET_BIT(DACx->SWTRIGR, + (DAC_Channel & DAC_SWTR_CHX_MASK)); +} + +/** + * @brief Set the data to be loaded in the data holding register + * in format 12 bits left alignment (LSB aligned on bit 0), + * for the selected DAC channel. + * @rmtoll DHR12R1 DACC1DHR LL_DAC_ConvertData12RightAligned\n + * DHR12R2 DACC2DHR LL_DAC_ConvertData12RightAligned + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param Data Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConvertData12RightAligned(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t Data) +{ + __IO uint32_t *preg = __DAC_PTR_REG_OFFSET(DACx->DHR12R1, (DAC_Channel >> DAC_REG_DHR12RX_REGOFFSET_BITOFFSET_POS) & DAC_REG_DHR_REGOFFSET_MASK_POSBIT0); + + MODIFY_REG(*preg, + DAC_DHR12R1_DACC1DHR, + Data); +} + +/** + * @brief Set the data to be loaded in the data holding register + * in format 12 bits left alignment (MSB aligned on bit 15), + * for the selected DAC channel. + * @rmtoll DHR12L1 DACC1DHR LL_DAC_ConvertData12LeftAligned\n + * DHR12L2 DACC2DHR LL_DAC_ConvertData12LeftAligned + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param Data Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConvertData12LeftAligned(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t Data) +{ + __IO uint32_t *preg = __DAC_PTR_REG_OFFSET(DACx->DHR12R1, (DAC_Channel >> DAC_REG_DHR12LX_REGOFFSET_BITOFFSET_POS) & DAC_REG_DHR_REGOFFSET_MASK_POSBIT0); + + MODIFY_REG(*preg, + DAC_DHR12L1_DACC1DHR, + Data); +} + +/** + * @brief Set the data to be loaded in the data holding register + * in format 8 bits left alignment (LSB aligned on bit 0), + * for the selected DAC channel. + * @rmtoll DHR8R1 DACC1DHR LL_DAC_ConvertData8RightAligned\n + * DHR8R2 DACC2DHR LL_DAC_ConvertData8RightAligned + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param Data Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConvertData8RightAligned(DAC_TypeDef *DACx, uint32_t DAC_Channel, uint32_t Data) +{ + __IO uint32_t *preg = __DAC_PTR_REG_OFFSET(DACx->DHR12R1, (DAC_Channel >> DAC_REG_DHR8RX_REGOFFSET_BITOFFSET_POS) & DAC_REG_DHR_REGOFFSET_MASK_POSBIT0); + + MODIFY_REG(*preg, + DAC_DHR8R1_DACC1DHR, + Data); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Set the data to be loaded in the data holding register + * in format 12 bits left alignment (LSB aligned on bit 0), + * for both DAC channels. + * @rmtoll DHR12RD DACC1DHR LL_DAC_ConvertDualData12RightAligned\n + * DHR12RD DACC2DHR LL_DAC_ConvertDualData12RightAligned + * @param DACx DAC instance + * @param DataChannel1 Value between Min_Data=0x000 and Max_Data=0xFFF + * @param DataChannel2 Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConvertDualData12RightAligned(DAC_TypeDef *DACx, uint32_t DataChannel1, + uint32_t DataChannel2) +{ + MODIFY_REG(DACx->DHR12RD, + (DAC_DHR12RD_DACC2DHR | DAC_DHR12RD_DACC1DHR), + ((DataChannel2 << DAC_DHR12RD_DACC2DHR_BITOFFSET_POS) | DataChannel1)); +} + +/** + * @brief Set the data to be loaded in the data holding register + * in format 12 bits left alignment (MSB aligned on bit 15), + * for both DAC channels. + * @rmtoll DHR12LD DACC1DHR LL_DAC_ConvertDualData12LeftAligned\n + * DHR12LD DACC2DHR LL_DAC_ConvertDualData12LeftAligned + * @param DACx DAC instance + * @param DataChannel1 Value between Min_Data=0x000 and Max_Data=0xFFF + * @param DataChannel2 Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConvertDualData12LeftAligned(DAC_TypeDef *DACx, uint32_t DataChannel1, uint32_t DataChannel2) +{ + /* Note: Data of DAC channel 2 shift value subtracted of 4 because */ + /* data on 16 bits and DAC channel 2 bits field is on the 12 MSB, */ + /* the 4 LSB must be taken into account for the shift value. */ + MODIFY_REG(DACx->DHR12LD, + (DAC_DHR12LD_DACC2DHR | DAC_DHR12LD_DACC1DHR), + ((DataChannel2 << (DAC_DHR12LD_DACC2DHR_BITOFFSET_POS - 4U)) | DataChannel1)); +} + +/** + * @brief Set the data to be loaded in the data holding register + * in format 8 bits left alignment (LSB aligned on bit 0), + * for both DAC channels. + * @rmtoll DHR8RD DACC1DHR LL_DAC_ConvertDualData8RightAligned\n + * DHR8RD DACC2DHR LL_DAC_ConvertDualData8RightAligned + * @param DACx DAC instance + * @param DataChannel1 Value between Min_Data=0x00 and Max_Data=0xFF + * @param DataChannel2 Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DAC_ConvertDualData8RightAligned(DAC_TypeDef *DACx, uint32_t DataChannel1, uint32_t DataChannel2) +{ + MODIFY_REG(DACx->DHR8RD, + (DAC_DHR8RD_DACC2DHR | DAC_DHR8RD_DACC1DHR), + ((DataChannel2 << DAC_DHR8RD_DACC2DHR_BITOFFSET_POS) | DataChannel1)); +} + +#endif /* DAC_CHANNEL2_SUPPORT */ +/** + * @brief Retrieve output data currently generated for the selected DAC channel. + * @note Whatever alignment and resolution settings + * (using functions "LL_DAC_ConvertData{8; 12}{Right; Left} Aligned()": + * @ref LL_DAC_ConvertData12RightAligned(), ...), + * output data format is 12 bits right aligned (LSB aligned on bit 0). + * @rmtoll DOR1 DACC1DOR LL_DAC_RetrieveOutputData\n + * DOR2 DACC2DOR LL_DAC_RetrieveOutputData + * @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 series, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_DAC_RetrieveOutputData(DAC_TypeDef *DACx, uint32_t DAC_Channel) +{ + __IO uint32_t const *preg = __DAC_PTR_REG_OFFSET(DACx->DOR1, (DAC_Channel >> DAC_REG_DORX_REGOFFSET_BITOFFSET_POS) & DAC_REG_DORX_REGOFFSET_MASK_POSBIT0); + + return (uint16_t) READ_BIT(*preg, DAC_DOR1_DACC1DOR); +} + +/** + * @} + */ + +/** @defgroup DAC_LL_EF_FLAG_Management FLAG Management + * @{ + */ +/** + * @brief Get DAC calibration offset flag for DAC channel 1 + * @rmtoll SR CAL_FLAG1 LL_DAC_IsActiveFlag_CAL1 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsActiveFlag_CAL1(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->SR, LL_DAC_FLAG_CAL1) == (LL_DAC_FLAG_CAL1)) ? 1UL : 0UL); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Get DAC calibration offset flag for DAC channel 2 + * @rmtoll SR CAL_FLAG2 LL_DAC_IsActiveFlag_CAL2 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsActiveFlag_CAL2(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->SR, LL_DAC_FLAG_CAL2) == (LL_DAC_FLAG_CAL2)) ? 1UL : 0UL); +} + +#endif /* DAC_CHANNEL2_SUPPORT */ +/** + * @brief Get DAC busy writing sample time flag for DAC channel 1 + * @rmtoll SR BWST1 LL_DAC_IsActiveFlag_BWST1 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsActiveFlag_BWST1(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->SR, LL_DAC_FLAG_BWST1) == (LL_DAC_FLAG_BWST1)) ? 1UL : 0UL); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Get DAC busy writing sample time flag for DAC channel 2 + * @rmtoll SR BWST2 LL_DAC_IsActiveFlag_BWST2 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsActiveFlag_BWST2(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->SR, LL_DAC_FLAG_BWST2) == (LL_DAC_FLAG_BWST2)) ? 1UL : 0UL); +} + +#endif /* DAC_CHANNEL2_SUPPORT */ +/** + * @brief Get DAC underrun flag for DAC channel 1 + * @rmtoll SR DMAUDR1 LL_DAC_IsActiveFlag_DMAUDR1 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsActiveFlag_DMAUDR1(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->SR, LL_DAC_FLAG_DMAUDR1) == (LL_DAC_FLAG_DMAUDR1)) ? 1UL : 0UL); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Get DAC underrun flag for DAC channel 2 + * @rmtoll SR DMAUDR2 LL_DAC_IsActiveFlag_DMAUDR2 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsActiveFlag_DMAUDR2(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->SR, LL_DAC_FLAG_DMAUDR2) == (LL_DAC_FLAG_DMAUDR2)) ? 1UL : 0UL); +} +#endif /* DAC_CHANNEL2_SUPPORT */ + +/** + * @brief Clear DAC underrun flag for DAC channel 1 + * @rmtoll SR DMAUDR1 LL_DAC_ClearFlag_DMAUDR1 + * @param DACx DAC instance + * @retval None + */ +__STATIC_INLINE void LL_DAC_ClearFlag_DMAUDR1(DAC_TypeDef *DACx) +{ + WRITE_REG(DACx->SR, LL_DAC_FLAG_DMAUDR1); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Clear DAC underrun flag for DAC channel 2 + * @rmtoll SR DMAUDR2 LL_DAC_ClearFlag_DMAUDR2 + * @param DACx DAC instance + * @retval None + */ +__STATIC_INLINE void LL_DAC_ClearFlag_DMAUDR2(DAC_TypeDef *DACx) +{ + WRITE_REG(DACx->SR, LL_DAC_FLAG_DMAUDR2); +} +#endif /* DAC_CHANNEL2_SUPPORT */ + +/** + * @} + */ + +/** @defgroup DAC_LL_EF_IT_Management IT management + * @{ + */ + +/** + * @brief Enable DMA underrun interrupt for DAC channel 1 + * @rmtoll CR DMAUDRIE1 LL_DAC_EnableIT_DMAUDR1 + * @param DACx DAC instance + * @retval None + */ +__STATIC_INLINE void LL_DAC_EnableIT_DMAUDR1(DAC_TypeDef *DACx) +{ + SET_BIT(DACx->CR, LL_DAC_IT_DMAUDRIE1); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Enable DMA underrun interrupt for DAC channel 2 + * @rmtoll CR DMAUDRIE2 LL_DAC_EnableIT_DMAUDR2 + * @param DACx DAC instance + * @retval None + */ +__STATIC_INLINE void LL_DAC_EnableIT_DMAUDR2(DAC_TypeDef *DACx) +{ + SET_BIT(DACx->CR, LL_DAC_IT_DMAUDRIE2); +} +#endif /* DAC_CHANNEL2_SUPPORT */ + +/** + * @brief Disable DMA underrun interrupt for DAC channel 1 + * @rmtoll CR DMAUDRIE1 LL_DAC_DisableIT_DMAUDR1 + * @param DACx DAC instance + * @retval None + */ +__STATIC_INLINE void LL_DAC_DisableIT_DMAUDR1(DAC_TypeDef *DACx) +{ + CLEAR_BIT(DACx->CR, LL_DAC_IT_DMAUDRIE1); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Disable DMA underrun interrupt for DAC channel 2 + * @rmtoll CR DMAUDRIE2 LL_DAC_DisableIT_DMAUDR2 + * @param DACx DAC instance + * @retval None + */ +__STATIC_INLINE void LL_DAC_DisableIT_DMAUDR2(DAC_TypeDef *DACx) +{ + CLEAR_BIT(DACx->CR, LL_DAC_IT_DMAUDRIE2); +} +#endif /* DAC_CHANNEL2_SUPPORT */ + +/** + * @brief Get DMA underrun interrupt for DAC channel 1 + * @rmtoll CR DMAUDRIE1 LL_DAC_IsEnabledIT_DMAUDR1 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsEnabledIT_DMAUDR1(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->CR, LL_DAC_IT_DMAUDRIE1) == (LL_DAC_IT_DMAUDRIE1)) ? 1UL : 0UL); +} + +#if defined(DAC_CHANNEL2_SUPPORT) +/** + * @brief Get DMA underrun interrupt for DAC channel 2 + * @rmtoll CR DMAUDRIE2 LL_DAC_IsEnabledIT_DMAUDR2 + * @param DACx DAC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DAC_IsEnabledIT_DMAUDR2(DAC_TypeDef *DACx) +{ + return ((READ_BIT(DACx->CR, LL_DAC_IT_DMAUDRIE2) == (LL_DAC_IT_DMAUDRIE2)) ? 1UL : 0UL); +} +#endif /* DAC_CHANNEL2_SUPPORT */ + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DAC_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_DAC_DeInit(DAC_TypeDef *DACx); +ErrorStatus LL_DAC_Init(DAC_TypeDef *DACx, uint32_t DAC_Channel, LL_DAC_InitTypeDef *DAC_InitStruct); +void LL_DAC_StructInit(LL_DAC_InitTypeDef *DAC_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DAC1 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_DAC_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dma.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dma.h new file mode 100644 index 0000000..5f93614 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dma.h @@ -0,0 +1,2430 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_dma.h + * @author MCD Application Team + * @brief Header file of DMA 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 STM32L4xx_LL_DMA_H +#define STM32L4xx_LL_DMA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" +#if defined(DMAMUX1) +#include "stm32l4xx_ll_dmamux.h" +#endif /* DMAMUX1 */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (DMA1) || defined (DMA2) + +/** @defgroup DMA_LL DMA + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup DMA_LL_Private_Variables DMA Private Variables + * @{ + */ +/* Array used to get the DMA channel register offset versus channel index LL_DMA_CHANNEL_x */ +static const uint8_t CHANNEL_OFFSET_TAB[] = +{ + (uint8_t)(DMA1_Channel1_BASE - DMA1_BASE), + (uint8_t)(DMA1_Channel2_BASE - DMA1_BASE), + (uint8_t)(DMA1_Channel3_BASE - DMA1_BASE), + (uint8_t)(DMA1_Channel4_BASE - DMA1_BASE), + (uint8_t)(DMA1_Channel5_BASE - DMA1_BASE), + (uint8_t)(DMA1_Channel6_BASE - DMA1_BASE), + (uint8_t)(DMA1_Channel7_BASE - DMA1_BASE) +}; +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +#if defined(DMAMUX1) +#else +/** @defgroup DMA_LL_Private_Constants DMA Private Constants + * @{ + */ +/* Define used to get CSELR register offset */ +#define DMA_CSELR_OFFSET (uint32_t)(DMA1_CSELR_BASE - DMA1_BASE) + +/* Defines used for the bit position in the register and perform offsets */ +#define DMA_POSITION_CSELR_CXS POSITION_VAL(DMA_CSELR_C1S << (Channel*4U)) +/** + * @} + */ +#endif /* DMAMUX1 */ +/* Private macros ------------------------------------------------------------*/ +#if defined(DMAMUX1) + +/** @defgroup DMA_LL_Private_Macros DMA Private Macros + * @{ + */ +/** + * @brief Helper macro to convert DMA Instance DMAx into DMAMUX channel + * @note DMAMUX channel 0 to 6 are mapped to DMA1 channel 1 to 7. + * DMAMUX channel 7 to 13 are mapped to DMA2 channel 1 to 7. + * @param __DMA_INSTANCE__ DMAx + * @retval Channel_Offset (LL_DMA_CHANNEL_7 or 0). + */ +#define __LL_DMA_INSTANCE_TO_DMAMUX_CHANNEL(__DMA_INSTANCE__) \ +(((__DMA_INSTANCE__) == DMA1) ? 0x00000000U : LL_DMA_CHANNEL_7) + +/** + * @} + */ +#else +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DMA_LL_Private_Macros DMA Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ +#endif /* DMAMUX1 */ +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DMA_LL_ES_INIT DMA Exported Init structure + * @{ + */ +typedef struct +{ + uint32_t PeriphOrM2MSrcAddress; /*!< Specifies the peripheral base address for DMA transfer + or as Source base address in case of memory to memory transfer direction. + + This parameter must be a value between Min_Data = 0 and Max_Data = 0xFFFFFFFF. */ + + uint32_t MemoryOrM2MDstAddress; /*!< Specifies the memory base address for DMA transfer + or as Destination base address in case of memory to memory transfer direction. + + This parameter must be a value between Min_Data = 0 and Max_Data = 0xFFFFFFFF. */ + + uint32_t Direction; /*!< Specifies if the data will be transferred from memory to peripheral, + from memory to memory or from peripheral to memory. + This parameter can be a value of @ref DMA_LL_EC_DIRECTION + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetDataTransferDirection(). */ + + uint32_t Mode; /*!< Specifies the normal or circular operation mode. + This parameter can be a value of @ref DMA_LL_EC_MODE + @note: The circular buffer mode cannot be used if the memory to memory + data transfer direction is configured on the selected Channel + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetMode(). */ + + uint32_t PeriphOrM2MSrcIncMode; /*!< Specifies whether the Peripheral address or Source address in case of memory to memory transfer direction + is incremented or not. + This parameter can be a value of @ref DMA_LL_EC_PERIPH + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetPeriphIncMode(). */ + + uint32_t MemoryOrM2MDstIncMode; /*!< Specifies whether the Memory address or Destination address in case of memory to memory transfer direction + is incremented or not. + This parameter can be a value of @ref DMA_LL_EC_MEMORY + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetMemoryIncMode(). */ + + uint32_t PeriphOrM2MSrcDataSize; /*!< Specifies the Peripheral data size alignment or Source data size alignment (byte, half word, word) + in case of memory to memory transfer direction. + This parameter can be a value of @ref DMA_LL_EC_PDATAALIGN + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetPeriphSize(). */ + + uint32_t MemoryOrM2MDstDataSize; /*!< Specifies the Memory data size alignment or Destination data size alignment (byte, half word, word) + in case of memory to memory transfer direction. + This parameter can be a value of @ref DMA_LL_EC_MDATAALIGN + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetMemorySize(). */ + + uint32_t NbData; /*!< Specifies the number of data to transfer, in data unit. + The data unit is equal to the source buffer configuration set in PeripheralSize + or MemorySize parameters depending in the transfer direction. + This parameter must be a value between Min_Data = 0 and Max_Data = 0x0000FFFF + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetDataLength(). */ + +#if defined(DMAMUX1) + uint32_t PeriphRequest; /*!< Specifies the peripheral request. + This parameter can be a value of @ref DMAMUX_LL_EC_REQUEST + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetPeriphRequest(). */ +#else + uint32_t PeriphRequest; /*!< Specifies the peripheral request. + This parameter can be a value of @ref DMA_LL_EC_REQUEST + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetPeriphRequest(). */ +#endif /* DMAMUX1 */ + + uint32_t Priority; /*!< Specifies the channel priority level. + This parameter can be a value of @ref DMA_LL_EC_PRIORITY + + This feature can be modified afterwards using unitary function @ref LL_DMA_SetChannelPriorityLevel(). */ + +} LL_DMA_InitTypeDef; +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DMA_LL_Exported_Constants DMA Exported Constants + * @{ + */ +/** @defgroup DMA_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_DMA_WriteReg function + * @{ + */ +#define LL_DMA_IFCR_CGIF1 DMA_IFCR_CGIF1 /*!< Channel 1 global flag */ +#define LL_DMA_IFCR_CTCIF1 DMA_IFCR_CTCIF1 /*!< Channel 1 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF1 DMA_IFCR_CHTIF1 /*!< Channel 1 half transfer flag */ +#define LL_DMA_IFCR_CTEIF1 DMA_IFCR_CTEIF1 /*!< Channel 1 transfer error flag */ +#define LL_DMA_IFCR_CGIF2 DMA_IFCR_CGIF2 /*!< Channel 2 global flag */ +#define LL_DMA_IFCR_CTCIF2 DMA_IFCR_CTCIF2 /*!< Channel 2 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF2 DMA_IFCR_CHTIF2 /*!< Channel 2 half transfer flag */ +#define LL_DMA_IFCR_CTEIF2 DMA_IFCR_CTEIF2 /*!< Channel 2 transfer error flag */ +#define LL_DMA_IFCR_CGIF3 DMA_IFCR_CGIF3 /*!< Channel 3 global flag */ +#define LL_DMA_IFCR_CTCIF3 DMA_IFCR_CTCIF3 /*!< Channel 3 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF3 DMA_IFCR_CHTIF3 /*!< Channel 3 half transfer flag */ +#define LL_DMA_IFCR_CTEIF3 DMA_IFCR_CTEIF3 /*!< Channel 3 transfer error flag */ +#define LL_DMA_IFCR_CGIF4 DMA_IFCR_CGIF4 /*!< Channel 4 global flag */ +#define LL_DMA_IFCR_CTCIF4 DMA_IFCR_CTCIF4 /*!< Channel 4 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF4 DMA_IFCR_CHTIF4 /*!< Channel 4 half transfer flag */ +#define LL_DMA_IFCR_CTEIF4 DMA_IFCR_CTEIF4 /*!< Channel 4 transfer error flag */ +#define LL_DMA_IFCR_CGIF5 DMA_IFCR_CGIF5 /*!< Channel 5 global flag */ +#define LL_DMA_IFCR_CTCIF5 DMA_IFCR_CTCIF5 /*!< Channel 5 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF5 DMA_IFCR_CHTIF5 /*!< Channel 5 half transfer flag */ +#define LL_DMA_IFCR_CTEIF5 DMA_IFCR_CTEIF5 /*!< Channel 5 transfer error flag */ +#define LL_DMA_IFCR_CGIF6 DMA_IFCR_CGIF6 /*!< Channel 6 global flag */ +#define LL_DMA_IFCR_CTCIF6 DMA_IFCR_CTCIF6 /*!< Channel 6 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF6 DMA_IFCR_CHTIF6 /*!< Channel 6 half transfer flag */ +#define LL_DMA_IFCR_CTEIF6 DMA_IFCR_CTEIF6 /*!< Channel 6 transfer error flag */ +#define LL_DMA_IFCR_CGIF7 DMA_IFCR_CGIF7 /*!< Channel 7 global flag */ +#define LL_DMA_IFCR_CTCIF7 DMA_IFCR_CTCIF7 /*!< Channel 7 transfer complete flag */ +#define LL_DMA_IFCR_CHTIF7 DMA_IFCR_CHTIF7 /*!< Channel 7 half transfer flag */ +#define LL_DMA_IFCR_CTEIF7 DMA_IFCR_CTEIF7 /*!< Channel 7 transfer error flag */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_DMA_ReadReg function + * @{ + */ +#define LL_DMA_ISR_GIF1 DMA_ISR_GIF1 /*!< Channel 1 global flag */ +#define LL_DMA_ISR_TCIF1 DMA_ISR_TCIF1 /*!< Channel 1 transfer complete flag */ +#define LL_DMA_ISR_HTIF1 DMA_ISR_HTIF1 /*!< Channel 1 half transfer flag */ +#define LL_DMA_ISR_TEIF1 DMA_ISR_TEIF1 /*!< Channel 1 transfer error flag */ +#define LL_DMA_ISR_GIF2 DMA_ISR_GIF2 /*!< Channel 2 global flag */ +#define LL_DMA_ISR_TCIF2 DMA_ISR_TCIF2 /*!< Channel 2 transfer complete flag */ +#define LL_DMA_ISR_HTIF2 DMA_ISR_HTIF2 /*!< Channel 2 half transfer flag */ +#define LL_DMA_ISR_TEIF2 DMA_ISR_TEIF2 /*!< Channel 2 transfer error flag */ +#define LL_DMA_ISR_GIF3 DMA_ISR_GIF3 /*!< Channel 3 global flag */ +#define LL_DMA_ISR_TCIF3 DMA_ISR_TCIF3 /*!< Channel 3 transfer complete flag */ +#define LL_DMA_ISR_HTIF3 DMA_ISR_HTIF3 /*!< Channel 3 half transfer flag */ +#define LL_DMA_ISR_TEIF3 DMA_ISR_TEIF3 /*!< Channel 3 transfer error flag */ +#define LL_DMA_ISR_GIF4 DMA_ISR_GIF4 /*!< Channel 4 global flag */ +#define LL_DMA_ISR_TCIF4 DMA_ISR_TCIF4 /*!< Channel 4 transfer complete flag */ +#define LL_DMA_ISR_HTIF4 DMA_ISR_HTIF4 /*!< Channel 4 half transfer flag */ +#define LL_DMA_ISR_TEIF4 DMA_ISR_TEIF4 /*!< Channel 4 transfer error flag */ +#define LL_DMA_ISR_GIF5 DMA_ISR_GIF5 /*!< Channel 5 global flag */ +#define LL_DMA_ISR_TCIF5 DMA_ISR_TCIF5 /*!< Channel 5 transfer complete flag */ +#define LL_DMA_ISR_HTIF5 DMA_ISR_HTIF5 /*!< Channel 5 half transfer flag */ +#define LL_DMA_ISR_TEIF5 DMA_ISR_TEIF5 /*!< Channel 5 transfer error flag */ +#define LL_DMA_ISR_GIF6 DMA_ISR_GIF6 /*!< Channel 6 global flag */ +#define LL_DMA_ISR_TCIF6 DMA_ISR_TCIF6 /*!< Channel 6 transfer complete flag */ +#define LL_DMA_ISR_HTIF6 DMA_ISR_HTIF6 /*!< Channel 6 half transfer flag */ +#define LL_DMA_ISR_TEIF6 DMA_ISR_TEIF6 /*!< Channel 6 transfer error flag */ +#define LL_DMA_ISR_GIF7 DMA_ISR_GIF7 /*!< Channel 7 global flag */ +#define LL_DMA_ISR_TCIF7 DMA_ISR_TCIF7 /*!< Channel 7 transfer complete flag */ +#define LL_DMA_ISR_HTIF7 DMA_ISR_HTIF7 /*!< Channel 7 half transfer flag */ +#define LL_DMA_ISR_TEIF7 DMA_ISR_TEIF7 /*!< Channel 7 transfer error flag */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_DMA_ReadReg and LL_DMA_WriteReg functions + * @{ + */ +#define LL_DMA_CCR_TCIE DMA_CCR_TCIE /*!< Transfer complete interrupt */ +#define LL_DMA_CCR_HTIE DMA_CCR_HTIE /*!< Half Transfer interrupt */ +#define LL_DMA_CCR_TEIE DMA_CCR_TEIE /*!< Transfer error interrupt */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_CHANNEL CHANNEL + * @{ + */ +#define LL_DMA_CHANNEL_1 0x00000000U /*!< DMA Channel 1 */ +#define LL_DMA_CHANNEL_2 0x00000001U /*!< DMA Channel 2 */ +#define LL_DMA_CHANNEL_3 0x00000002U /*!< DMA Channel 3 */ +#define LL_DMA_CHANNEL_4 0x00000003U /*!< DMA Channel 4 */ +#define LL_DMA_CHANNEL_5 0x00000004U /*!< DMA Channel 5 */ +#define LL_DMA_CHANNEL_6 0x00000005U /*!< DMA Channel 6 */ +#define LL_DMA_CHANNEL_7 0x00000006U /*!< DMA Channel 7 */ +#if defined(USE_FULL_LL_DRIVER) +#define LL_DMA_CHANNEL_ALL 0xFFFF0000U /*!< DMA Channel all (used only for function @ref LL_DMA_DeInit(). */ +#endif /*USE_FULL_LL_DRIVER*/ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_DIRECTION Transfer Direction + * @{ + */ +#define LL_DMA_DIRECTION_PERIPH_TO_MEMORY 0x00000000U /*!< Peripheral to memory direction */ +#define LL_DMA_DIRECTION_MEMORY_TO_PERIPH DMA_CCR_DIR /*!< Memory to peripheral direction */ +#define LL_DMA_DIRECTION_MEMORY_TO_MEMORY DMA_CCR_MEM2MEM /*!< Memory to memory direction */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_MODE Transfer mode + * @{ + */ +#define LL_DMA_MODE_NORMAL 0x00000000U /*!< Normal Mode */ +#define LL_DMA_MODE_CIRCULAR DMA_CCR_CIRC /*!< Circular Mode */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_PERIPH Peripheral increment mode + * @{ + */ +#define LL_DMA_PERIPH_INCREMENT DMA_CCR_PINC /*!< Peripheral increment mode Enable */ +#define LL_DMA_PERIPH_NOINCREMENT 0x00000000U /*!< Peripheral increment mode Disable */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_MEMORY Memory increment mode + * @{ + */ +#define LL_DMA_MEMORY_INCREMENT DMA_CCR_MINC /*!< Memory increment mode Enable */ +#define LL_DMA_MEMORY_NOINCREMENT 0x00000000U /*!< Memory increment mode Disable */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_PDATAALIGN Peripheral data alignment + * @{ + */ +#define LL_DMA_PDATAALIGN_BYTE 0x00000000U /*!< Peripheral data alignment : Byte */ +#define LL_DMA_PDATAALIGN_HALFWORD DMA_CCR_PSIZE_0 /*!< Peripheral data alignment : HalfWord */ +#define LL_DMA_PDATAALIGN_WORD DMA_CCR_PSIZE_1 /*!< Peripheral data alignment : Word */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_MDATAALIGN Memory data alignment + * @{ + */ +#define LL_DMA_MDATAALIGN_BYTE 0x00000000U /*!< Memory data alignment : Byte */ +#define LL_DMA_MDATAALIGN_HALFWORD DMA_CCR_MSIZE_0 /*!< Memory data alignment : HalfWord */ +#define LL_DMA_MDATAALIGN_WORD DMA_CCR_MSIZE_1 /*!< Memory data alignment : Word */ +/** + * @} + */ + +/** @defgroup DMA_LL_EC_PRIORITY Transfer Priority level + * @{ + */ +#define LL_DMA_PRIORITY_LOW 0x00000000U /*!< Priority level : Low */ +#define LL_DMA_PRIORITY_MEDIUM DMA_CCR_PL_0 /*!< Priority level : Medium */ +#define LL_DMA_PRIORITY_HIGH DMA_CCR_PL_1 /*!< Priority level : High */ +#define LL_DMA_PRIORITY_VERYHIGH DMA_CCR_PL /*!< Priority level : Very_High */ +/** + * @} + */ + +#if !defined (DMAMUX1) +/** @defgroup DMA_LL_EC_REQUEST Transfer peripheral request + * @{ + */ +#define LL_DMA_REQUEST_0 0x00000000U /*!< DMA peripheral request 0 */ +#define LL_DMA_REQUEST_1 0x00000001U /*!< DMA peripheral request 1 */ +#define LL_DMA_REQUEST_2 0x00000002U /*!< DMA peripheral request 2 */ +#define LL_DMA_REQUEST_3 0x00000003U /*!< DMA peripheral request 3 */ +#define LL_DMA_REQUEST_4 0x00000004U /*!< DMA peripheral request 4 */ +#define LL_DMA_REQUEST_5 0x00000005U /*!< DMA peripheral request 5 */ +#define LL_DMA_REQUEST_6 0x00000006U /*!< DMA peripheral request 6 */ +#define LL_DMA_REQUEST_7 0x00000007U /*!< DMA peripheral request 7 */ +/** + * @} + */ +#endif /* !defined DMAMUX1 */ +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup DMA_LL_Exported_Macros DMA Exported Macros + * @{ + */ + +/** @defgroup DMA_LL_EM_WRITE_READ Common Write and read registers macros + * @{ + */ +/** + * @brief Write a value in DMA register + * @param __INSTANCE__ DMA Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_DMA_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in DMA register + * @param __INSTANCE__ DMA Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_DMA_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup DMA_LL_EM_CONVERT_DMAxCHANNELy Convert DMAxChannely + * @{ + */ +/** + * @brief Convert DMAx_Channely into DMAx + * @param __CHANNEL_INSTANCE__ DMAx_Channely + * @retval DMAx + */ +#if defined(DMA2) +#define __LL_DMA_GET_INSTANCE(__CHANNEL_INSTANCE__) \ +(((uint32_t)(__CHANNEL_INSTANCE__) > ((uint32_t)DMA1_Channel7)) ? DMA2 : DMA1) +#else +#define __LL_DMA_GET_INSTANCE(__CHANNEL_INSTANCE__) (DMA1) +#endif + +/** + * @brief Convert DMAx_Channely into LL_DMA_CHANNEL_y + * @param __CHANNEL_INSTANCE__ DMAx_Channely + * @retval LL_DMA_CHANNEL_y + */ +#if defined (DMA2) +#if defined (DMA2_Channel6) && defined (DMA2_Channel7) +#define __LL_DMA_GET_CHANNEL(__CHANNEL_INSTANCE__) \ +(((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel1)) ? LL_DMA_CHANNEL_1 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel1)) ? LL_DMA_CHANNEL_1 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel2)) ? LL_DMA_CHANNEL_2 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel2)) ? LL_DMA_CHANNEL_2 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel3)) ? LL_DMA_CHANNEL_3 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel3)) ? LL_DMA_CHANNEL_3 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel4)) ? LL_DMA_CHANNEL_4 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel4)) ? LL_DMA_CHANNEL_4 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel5)) ? LL_DMA_CHANNEL_5 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel5)) ? LL_DMA_CHANNEL_5 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel6)) ? LL_DMA_CHANNEL_6 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel6)) ? LL_DMA_CHANNEL_6 : \ + LL_DMA_CHANNEL_7) +#else +#define __LL_DMA_GET_CHANNEL(__CHANNEL_INSTANCE__) \ +(((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel1)) ? LL_DMA_CHANNEL_1 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel1)) ? LL_DMA_CHANNEL_1 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel2)) ? LL_DMA_CHANNEL_2 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel2)) ? LL_DMA_CHANNEL_2 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel3)) ? LL_DMA_CHANNEL_3 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel3)) ? LL_DMA_CHANNEL_3 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel4)) ? LL_DMA_CHANNEL_4 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel4)) ? LL_DMA_CHANNEL_4 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel5)) ? LL_DMA_CHANNEL_5 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA2_Channel5)) ? LL_DMA_CHANNEL_5 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel6)) ? LL_DMA_CHANNEL_6 : \ + LL_DMA_CHANNEL_7) +#endif +#else +#define __LL_DMA_GET_CHANNEL(__CHANNEL_INSTANCE__) \ +(((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel1)) ? LL_DMA_CHANNEL_1 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel2)) ? LL_DMA_CHANNEL_2 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel3)) ? LL_DMA_CHANNEL_3 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel4)) ? LL_DMA_CHANNEL_4 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel5)) ? LL_DMA_CHANNEL_5 : \ + ((uint32_t)(__CHANNEL_INSTANCE__) == ((uint32_t)DMA1_Channel6)) ? LL_DMA_CHANNEL_6 : \ + LL_DMA_CHANNEL_7) +#endif + +/** + * @brief Convert DMA Instance DMAx and LL_DMA_CHANNEL_y into DMAx_Channely + * @param __DMA_INSTANCE__ DMAx + * @param __CHANNEL__ LL_DMA_CHANNEL_y + * @retval DMAx_Channely + */ +#if defined (DMA2) +#if defined (DMA2_Channel6) && defined (DMA2_Channel7) +#define __LL_DMA_GET_CHANNEL_INSTANCE(__DMA_INSTANCE__, __CHANNEL__) \ +((((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_1))) ? DMA1_Channel1 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_1))) ? DMA2_Channel1 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_2))) ? DMA1_Channel2 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_2))) ? DMA2_Channel2 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_3))) ? DMA1_Channel3 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_3))) ? DMA2_Channel3 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_4))) ? DMA1_Channel4 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_4))) ? DMA2_Channel4 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_5))) ? DMA1_Channel5 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_5))) ? DMA2_Channel5 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_6))) ? DMA1_Channel6 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_6))) ? DMA2_Channel6 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_7))) ? DMA1_Channel7 : \ + DMA2_Channel7) +#else +#define __LL_DMA_GET_CHANNEL_INSTANCE(__DMA_INSTANCE__, __CHANNEL__) \ +((((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_1))) ? DMA1_Channel1 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_1))) ? DMA2_Channel1 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_2))) ? DMA1_Channel2 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_2))) ? DMA2_Channel2 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_3))) ? DMA1_Channel3 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_3))) ? DMA2_Channel3 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_4))) ? DMA1_Channel4 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_4))) ? DMA2_Channel4 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_5))) ? DMA1_Channel5 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA2)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_5))) ? DMA2_Channel5 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_6))) ? DMA1_Channel6 : \ + DMA1_Channel7) +#endif +#else +#define __LL_DMA_GET_CHANNEL_INSTANCE(__DMA_INSTANCE__, __CHANNEL__) \ +((((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_1))) ? DMA1_Channel1 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_2))) ? DMA1_Channel2 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_3))) ? DMA1_Channel3 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_4))) ? DMA1_Channel4 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_5))) ? DMA1_Channel5 : \ + (((uint32_t)(__DMA_INSTANCE__) == ((uint32_t)DMA1)) && ((uint32_t)(__CHANNEL__) == ((uint32_t)LL_DMA_CHANNEL_6))) ? DMA1_Channel6 : \ + DMA1_Channel7) +#endif + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DMA_LL_Exported_Functions DMA Exported Functions + * @{ + */ + +/** @defgroup DMA_LL_EF_Configuration Configuration + * @{ + */ +/** + * @brief Enable DMA channel. + * @rmtoll CCR EN LL_DMA_EnableChannel + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_EnableChannel(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + SET_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_EN); +} + +/** + * @brief Disable DMA channel. + * @rmtoll CCR EN LL_DMA_DisableChannel + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_DisableChannel(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + CLEAR_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_EN); +} + +/** + * @brief Check if DMA channel is enabled or disabled. + * @rmtoll CCR EN LL_DMA_IsEnabledChannel + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsEnabledChannel(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return ((READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_EN) == (DMA_CCR_EN)) ? 1UL : 0UL); +} + +/** + * @brief Configure all parameters link to DMA transfer. + * @rmtoll CCR DIR LL_DMA_ConfigTransfer\n + * CCR MEM2MEM LL_DMA_ConfigTransfer\n + * CCR CIRC LL_DMA_ConfigTransfer\n + * CCR PINC LL_DMA_ConfigTransfer\n + * CCR MINC LL_DMA_ConfigTransfer\n + * CCR PSIZE LL_DMA_ConfigTransfer\n + * CCR MSIZE LL_DMA_ConfigTransfer\n + * CCR PL LL_DMA_ConfigTransfer + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param Configuration This parameter must be a combination of all the following values: + * @arg @ref LL_DMA_DIRECTION_PERIPH_TO_MEMORY or @ref LL_DMA_DIRECTION_MEMORY_TO_PERIPH or @ref LL_DMA_DIRECTION_MEMORY_TO_MEMORY + * @arg @ref LL_DMA_MODE_NORMAL or @ref LL_DMA_MODE_CIRCULAR + * @arg @ref LL_DMA_PERIPH_INCREMENT or @ref LL_DMA_PERIPH_NOINCREMENT + * @arg @ref LL_DMA_MEMORY_INCREMENT or @ref LL_DMA_MEMORY_NOINCREMENT + * @arg @ref LL_DMA_PDATAALIGN_BYTE or @ref LL_DMA_PDATAALIGN_HALFWORD or @ref LL_DMA_PDATAALIGN_WORD + * @arg @ref LL_DMA_MDATAALIGN_BYTE or @ref LL_DMA_MDATAALIGN_HALFWORD or @ref LL_DMA_MDATAALIGN_WORD + * @arg @ref LL_DMA_PRIORITY_LOW or @ref LL_DMA_PRIORITY_MEDIUM or @ref LL_DMA_PRIORITY_HIGH or @ref LL_DMA_PRIORITY_VERYHIGH + * @retval None + */ +__STATIC_INLINE void LL_DMA_ConfigTransfer(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t Configuration) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_DIR | DMA_CCR_MEM2MEM | DMA_CCR_CIRC | DMA_CCR_PINC | DMA_CCR_MINC | DMA_CCR_PSIZE | DMA_CCR_MSIZE | DMA_CCR_PL, + Configuration); +} + +/** + * @brief Set Data transfer direction (read from peripheral or from memory). + * @rmtoll CCR DIR LL_DMA_SetDataTransferDirection\n + * CCR MEM2MEM LL_DMA_SetDataTransferDirection + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param Direction This parameter can be one of the following values: + * @arg @ref LL_DMA_DIRECTION_PERIPH_TO_MEMORY + * @arg @ref LL_DMA_DIRECTION_MEMORY_TO_PERIPH + * @arg @ref LL_DMA_DIRECTION_MEMORY_TO_MEMORY + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetDataTransferDirection(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t Direction) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_DIR | DMA_CCR_MEM2MEM, Direction); +} + +/** + * @brief Get Data transfer direction (read from peripheral or from memory). + * @rmtoll CCR DIR LL_DMA_GetDataTransferDirection\n + * CCR MEM2MEM LL_DMA_GetDataTransferDirection + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_DIRECTION_PERIPH_TO_MEMORY + * @arg @ref LL_DMA_DIRECTION_MEMORY_TO_PERIPH + * @arg @ref LL_DMA_DIRECTION_MEMORY_TO_MEMORY + */ +__STATIC_INLINE uint32_t LL_DMA_GetDataTransferDirection(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_DIR | DMA_CCR_MEM2MEM)); +} + +/** + * @brief Set DMA mode circular or normal. + * @note The circular buffer mode cannot be used if the memory-to-memory + * data transfer is configured on the selected Channel. + * @rmtoll CCR CIRC LL_DMA_SetMode + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_DMA_MODE_NORMAL + * @arg @ref LL_DMA_MODE_CIRCULAR + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetMode(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t Mode) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_CIRC, + Mode); +} + +/** + * @brief Get DMA mode circular or normal. + * @rmtoll CCR CIRC LL_DMA_GetMode + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_MODE_NORMAL + * @arg @ref LL_DMA_MODE_CIRCULAR + */ +__STATIC_INLINE uint32_t LL_DMA_GetMode(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_CIRC)); +} + +/** + * @brief Set Peripheral increment mode. + * @rmtoll CCR PINC LL_DMA_SetPeriphIncMode + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param PeriphOrM2MSrcIncMode This parameter can be one of the following values: + * @arg @ref LL_DMA_PERIPH_INCREMENT + * @arg @ref LL_DMA_PERIPH_NOINCREMENT + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetPeriphIncMode(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t PeriphOrM2MSrcIncMode) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_PINC, + PeriphOrM2MSrcIncMode); +} + +/** + * @brief Get Peripheral increment mode. + * @rmtoll CCR PINC LL_DMA_GetPeriphIncMode + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_PERIPH_INCREMENT + * @arg @ref LL_DMA_PERIPH_NOINCREMENT + */ +__STATIC_INLINE uint32_t LL_DMA_GetPeriphIncMode(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_PINC)); +} + +/** + * @brief Set Memory increment mode. + * @rmtoll CCR MINC LL_DMA_SetMemoryIncMode + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param MemoryOrM2MDstIncMode This parameter can be one of the following values: + * @arg @ref LL_DMA_MEMORY_INCREMENT + * @arg @ref LL_DMA_MEMORY_NOINCREMENT + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetMemoryIncMode(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t MemoryOrM2MDstIncMode) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_MINC, + MemoryOrM2MDstIncMode); +} + +/** + * @brief Get Memory increment mode. + * @rmtoll CCR MINC LL_DMA_GetMemoryIncMode + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_MEMORY_INCREMENT + * @arg @ref LL_DMA_MEMORY_NOINCREMENT + */ +__STATIC_INLINE uint32_t LL_DMA_GetMemoryIncMode(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_MINC)); +} + +/** + * @brief Set Peripheral size. + * @rmtoll CCR PSIZE LL_DMA_SetPeriphSize + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param PeriphOrM2MSrcDataSize This parameter can be one of the following values: + * @arg @ref LL_DMA_PDATAALIGN_BYTE + * @arg @ref LL_DMA_PDATAALIGN_HALFWORD + * @arg @ref LL_DMA_PDATAALIGN_WORD + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetPeriphSize(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t PeriphOrM2MSrcDataSize) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_PSIZE, + PeriphOrM2MSrcDataSize); +} + +/** + * @brief Get Peripheral size. + * @rmtoll CCR PSIZE LL_DMA_GetPeriphSize + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_PDATAALIGN_BYTE + * @arg @ref LL_DMA_PDATAALIGN_HALFWORD + * @arg @ref LL_DMA_PDATAALIGN_WORD + */ +__STATIC_INLINE uint32_t LL_DMA_GetPeriphSize(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_PSIZE)); +} + +/** + * @brief Set Memory size. + * @rmtoll CCR MSIZE LL_DMA_SetMemorySize + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param MemoryOrM2MDstDataSize This parameter can be one of the following values: + * @arg @ref LL_DMA_MDATAALIGN_BYTE + * @arg @ref LL_DMA_MDATAALIGN_HALFWORD + * @arg @ref LL_DMA_MDATAALIGN_WORD + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetMemorySize(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t MemoryOrM2MDstDataSize) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_MSIZE, + MemoryOrM2MDstDataSize); +} + +/** + * @brief Get Memory size. + * @rmtoll CCR MSIZE LL_DMA_GetMemorySize + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_MDATAALIGN_BYTE + * @arg @ref LL_DMA_MDATAALIGN_HALFWORD + * @arg @ref LL_DMA_MDATAALIGN_WORD + */ +__STATIC_INLINE uint32_t LL_DMA_GetMemorySize(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_MSIZE)); +} + +/** + * @brief Set Channel priority level. + * @rmtoll CCR PL LL_DMA_SetChannelPriorityLevel + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param Priority This parameter can be one of the following values: + * @arg @ref LL_DMA_PRIORITY_LOW + * @arg @ref LL_DMA_PRIORITY_MEDIUM + * @arg @ref LL_DMA_PRIORITY_HIGH + * @arg @ref LL_DMA_PRIORITY_VERYHIGH + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetChannelPriorityLevel(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t Priority) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_PL, + Priority); +} + +/** + * @brief Get Channel priority level. + * @rmtoll CCR PL LL_DMA_GetChannelPriorityLevel + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_PRIORITY_LOW + * @arg @ref LL_DMA_PRIORITY_MEDIUM + * @arg @ref LL_DMA_PRIORITY_HIGH + * @arg @ref LL_DMA_PRIORITY_VERYHIGH + */ +__STATIC_INLINE uint32_t LL_DMA_GetChannelPriorityLevel(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_PL)); +} + +/** + * @brief Set Number of data to transfer. + * @note This action has no effect if + * channel is enabled. + * @rmtoll CNDTR NDT LL_DMA_SetDataLength + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param NbData Between Min_Data = 0 and Max_Data = 0x0000FFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetDataLength(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t NbData) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + MODIFY_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CNDTR, + DMA_CNDTR_NDT, NbData); +} + +/** + * @brief Get Number of data to transfer. + * @note Once the channel is enabled, the return value indicate the + * remaining bytes to be transmitted. + * @rmtoll CNDTR NDT LL_DMA_GetDataLength + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA_GetDataLength(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CNDTR, + DMA_CNDTR_NDT)); +} + +/** + * @brief Configure the Source and Destination addresses. + * @note This API must not be called when the DMA channel is enabled. + * @note Each peripheral using DMA provides an API to get directly the register address (LL_PPP_DMA_GetRegAddr). + * @rmtoll CPAR PA LL_DMA_ConfigAddresses\n + * CMAR MA LL_DMA_ConfigAddresses + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param SrcAddress Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + * @param DstAddress Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + * @param Direction This parameter can be one of the following values: + * @arg @ref LL_DMA_DIRECTION_PERIPH_TO_MEMORY + * @arg @ref LL_DMA_DIRECTION_MEMORY_TO_PERIPH + * @arg @ref LL_DMA_DIRECTION_MEMORY_TO_MEMORY + * @retval None + */ +__STATIC_INLINE void LL_DMA_ConfigAddresses(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t SrcAddress, + uint32_t DstAddress, uint32_t Direction) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + /* Direction Memory to Periph */ + if (Direction == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) + { + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CMAR, SrcAddress); + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CPAR, DstAddress); + } + /* Direction Periph to Memory and Memory to Memory */ + else + { + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CPAR, SrcAddress); + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CMAR, DstAddress); + } +} + +/** + * @brief Set the Memory address. + * @note Interface used for direction LL_DMA_DIRECTION_PERIPH_TO_MEMORY or LL_DMA_DIRECTION_MEMORY_TO_PERIPH only. + * @note This API must not be called when the DMA channel is enabled. + * @rmtoll CMAR MA LL_DMA_SetMemoryAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param MemoryAddress Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetMemoryAddress(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t MemoryAddress) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CMAR, MemoryAddress); +} + +/** + * @brief Set the Peripheral address. + * @note Interface used for direction LL_DMA_DIRECTION_PERIPH_TO_MEMORY or LL_DMA_DIRECTION_MEMORY_TO_PERIPH only. + * @note This API must not be called when the DMA channel is enabled. + * @rmtoll CPAR PA LL_DMA_SetPeriphAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param PeriphAddress Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetPeriphAddress(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t PeriphAddress) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CPAR, PeriphAddress); +} + +/** + * @brief Get Memory address. + * @note Interface used for direction LL_DMA_DIRECTION_PERIPH_TO_MEMORY or LL_DMA_DIRECTION_MEMORY_TO_PERIPH only. + * @rmtoll CMAR MA LL_DMA_GetMemoryAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA_GetMemoryAddress(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CMAR)); +} + +/** + * @brief Get Peripheral address. + * @note Interface used for direction LL_DMA_DIRECTION_PERIPH_TO_MEMORY or LL_DMA_DIRECTION_MEMORY_TO_PERIPH only. + * @rmtoll CPAR PA LL_DMA_GetPeriphAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA_GetPeriphAddress(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CPAR)); +} + +/** + * @brief Set the Memory to Memory Source address. + * @note Interface used for direction LL_DMA_DIRECTION_MEMORY_TO_MEMORY only. + * @note This API must not be called when the DMA channel is enabled. + * @rmtoll CPAR PA LL_DMA_SetM2MSrcAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param MemoryAddress Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetM2MSrcAddress(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t MemoryAddress) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CPAR, MemoryAddress); +} + +/** + * @brief Set the Memory to Memory Destination address. + * @note Interface used for direction LL_DMA_DIRECTION_MEMORY_TO_MEMORY only. + * @note This API must not be called when the DMA channel is enabled. + * @rmtoll CMAR MA LL_DMA_SetM2MDstAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param MemoryAddress Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetM2MDstAddress(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t MemoryAddress) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + WRITE_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CMAR, MemoryAddress); +} + +/** + * @brief Get the Memory to Memory Source address. + * @note Interface used for direction LL_DMA_DIRECTION_MEMORY_TO_MEMORY only. + * @rmtoll CPAR PA LL_DMA_GetM2MSrcAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA_GetM2MSrcAddress(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CPAR)); +} + +/** + * @brief Get the Memory to Memory Destination address. + * @note Interface used for direction LL_DMA_DIRECTION_MEMORY_TO_MEMORY only. + * @rmtoll CMAR MA LL_DMA_GetM2MDstAddress + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Between Min_Data = 0 and Max_Data = 0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA_GetM2MDstAddress(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return (READ_REG(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CMAR)); +} + +#if defined(DMAMUX1) +/** + * @brief Set DMA request for DMA Channels on DMAMUX Channel x. + * @note DMAMUX channel 0 to 6 are mapped to DMA1 channel 1 to 7. + * DMAMUX channel 7 to 13 are mapped to DMA2 channel 1 to 7. + * @rmtoll CxCR DMAREQ_ID LL_DMA_SetPeriphRequest + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param Request This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_MEM2MEM + * @arg @ref LL_DMAMUX_REQ_GENERATOR0 + * @arg @ref LL_DMAMUX_REQ_GENERATOR1 + * @arg @ref LL_DMAMUX_REQ_GENERATOR2 + * @arg @ref LL_DMAMUX_REQ_GENERATOR3 + * @arg @ref LL_DMAMUX_REQ_ADC1 + * @arg @ref LL_DMAMUX_REQ_ADC2 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH1 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM6_UP + * @arg @ref LL_DMAMUX_REQ_TIM7_UP + * @arg @ref LL_DMAMUX_REQ_SPI1_RX + * @arg @ref LL_DMAMUX_REQ_SPI1_TX + * @arg @ref LL_DMAMUX_REQ_SPI2_RX + * @arg @ref LL_DMAMUX_REQ_SPI2_TX + * @arg @ref LL_DMAMUX_REQ_SPI3_RX + * @arg @ref LL_DMAMUX_REQ_SPI3_TX + * @arg @ref LL_DMAMUX_REQ_I2C1_RX + * @arg @ref LL_DMAMUX_REQ_I2C1_TX + * @arg @ref LL_DMAMUX_REQ_I2C2_RX + * @arg @ref LL_DMAMUX_REQ_I2C2_TX + * @arg @ref LL_DMAMUX_REQ_I2C3_RX + * @arg @ref LL_DMAMUX_REQ_I2C3_TX + * @arg @ref LL_DMAMUX_REQ_I2C4_RX + * @arg @ref LL_DMAMUX_REQ_I2C4_TX + * @arg @ref LL_DMAMUX_REQ_USART1_RX + * @arg @ref LL_DMAMUX_REQ_USART1_TX + * @arg @ref LL_DMAMUX_REQ_USART2_RX + * @arg @ref LL_DMAMUX_REQ_USART2_TX + * @arg @ref LL_DMAMUX_REQ_USART3_RX + * @arg @ref LL_DMAMUX_REQ_USART3_TX + * @arg @ref LL_DMAMUX_REQ_UART4_RX + * @arg @ref LL_DMAMUX_REQ_UART4_TX + * @arg @ref LL_DMAMUX_REQ_UART5_RX + * @arg @ref LL_DMAMUX_REQ_UART5_TX + * @arg @ref LL_DMAMUX_REQ_LPUART1_RX + * @arg @ref LL_DMAMUX_REQ_LPUART1_TX + * @arg @ref LL_DMAMUX_REQ_SAI1_A + * @arg @ref LL_DMAMUX_REQ_SAI1_B + * @arg @ref LL_DMAMUX_REQ_SAI2_A + * @arg @ref LL_DMAMUX_REQ_SAI2_B + * @arg @ref LL_DMAMUX_REQ_OSPI1 + * @arg @ref LL_DMAMUX_REQ_OSPI2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM1_UP + * @arg @ref LL_DMAMUX_REQ_TIM1_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM1_COM + * @arg @ref LL_DMAMUX_REQ_TIM8_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM8_UP + * @arg @ref LL_DMAMUX_REQ_TIM8_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM8_COM + * @arg @ref LL_DMAMUX_REQ_TIM2_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM2_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM3_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM4_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM4_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM5_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM15_UP + * @arg @ref LL_DMAMUX_REQ_TIM15_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_COM + * @arg @ref LL_DMAMUX_REQ_TIM16_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM16_UP + * @arg @ref LL_DMAMUX_REQ_TIM17_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM17_UP + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT0 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT1 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT2 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT3 + * @arg @ref LL_DMAMUX_REQ_DCMI + * @arg @ref LL_DMAMUX_REQ_DCMI_PSSI + * @arg @ref LL_DMAMUX_REQ_AES_IN + * @arg @ref LL_DMAMUX_REQ_AES_OUT + * @arg @ref LL_DMAMUX_REQ_HASH_IN + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetPeriphRequest(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t Request) +{ + uint32_t dmamux_ccr_offset = ((((uint32_t)DMAx ^ (uint32_t)DMA1) >> 10U) * 7U); + MODIFY_REG((DMAMUX1_Channel0 + Channel + dmamux_ccr_offset)->CCR, DMAMUX_CxCR_DMAREQ_ID, Request); +} + +/** + * @brief Get DMA request for DMA Channels on DMAMUX Channel x. + * @note DMAMUX channel 0 to 6 are mapped to DMA1 channel 1 to 7. + * DMAMUX channel 7 to 13 are mapped to DMA2 channel 1 to 7. + * @rmtoll CxCR DMAREQ_ID LL_DMA_GetPeriphRequest + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_MEM2MEM + * @arg @ref LL_DMAMUX_REQ_GENERATOR0 + * @arg @ref LL_DMAMUX_REQ_GENERATOR1 + * @arg @ref LL_DMAMUX_REQ_GENERATOR2 + * @arg @ref LL_DMAMUX_REQ_GENERATOR3 + * @arg @ref LL_DMAMUX_REQ_ADC1 + * @arg @ref LL_DMAMUX_REQ_ADC2 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH1 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM6_UP + * @arg @ref LL_DMAMUX_REQ_TIM7_UP + * @arg @ref LL_DMAMUX_REQ_SPI1_RX + * @arg @ref LL_DMAMUX_REQ_SPI1_TX + * @arg @ref LL_DMAMUX_REQ_SPI2_RX + * @arg @ref LL_DMAMUX_REQ_SPI2_TX + * @arg @ref LL_DMAMUX_REQ_SPI3_RX + * @arg @ref LL_DMAMUX_REQ_SPI3_TX + * @arg @ref LL_DMAMUX_REQ_I2C1_RX + * @arg @ref LL_DMAMUX_REQ_I2C1_TX + * @arg @ref LL_DMAMUX_REQ_I2C2_RX + * @arg @ref LL_DMAMUX_REQ_I2C2_TX + * @arg @ref LL_DMAMUX_REQ_I2C3_RX + * @arg @ref LL_DMAMUX_REQ_I2C3_TX + * @arg @ref LL_DMAMUX_REQ_I2C4_RX + * @arg @ref LL_DMAMUX_REQ_I2C4_TX + * @arg @ref LL_DMAMUX_REQ_USART1_RX + * @arg @ref LL_DMAMUX_REQ_USART1_TX + * @arg @ref LL_DMAMUX_REQ_USART2_RX + * @arg @ref LL_DMAMUX_REQ_USART2_TX + * @arg @ref LL_DMAMUX_REQ_USART3_RX + * @arg @ref LL_DMAMUX_REQ_USART3_TX + * @arg @ref LL_DMAMUX_REQ_UART4_RX + * @arg @ref LL_DMAMUX_REQ_UART4_TX + * @arg @ref LL_DMAMUX_REQ_UART5_RX + * @arg @ref LL_DMAMUX_REQ_UART5_TX + * @arg @ref LL_DMAMUX_REQ_LPUART1_RX + * @arg @ref LL_DMAMUX_REQ_LPUART1_TX + * @arg @ref LL_DMAMUX_REQ_SAI1_A + * @arg @ref LL_DMAMUX_REQ_SAI1_B + * @arg @ref LL_DMAMUX_REQ_SAI2_A + * @arg @ref LL_DMAMUX_REQ_SAI2_B + * @arg @ref LL_DMAMUX_REQ_OSPI1 + * @arg @ref LL_DMAMUX_REQ_OSPI2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM1_UP + * @arg @ref LL_DMAMUX_REQ_TIM1_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM1_COM + * @arg @ref LL_DMAMUX_REQ_TIM8_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM8_UP + * @arg @ref LL_DMAMUX_REQ_TIM8_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM8_COM + * @arg @ref LL_DMAMUX_REQ_TIM2_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM2_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM3_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM4_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM4_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM5_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM15_UP + * @arg @ref LL_DMAMUX_REQ_TIM15_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_COM + * @arg @ref LL_DMAMUX_REQ_TIM16_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM16_UP + * @arg @ref LL_DMAMUX_REQ_TIM17_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM17_UP + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT0 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT1 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT2 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT3 + * @arg @ref LL_DMAMUX_REQ_DCMI + * @arg @ref LL_DMAMUX_REQ_DCMI_PSSI + * @arg @ref LL_DMAMUX_REQ_AES_IN + * @arg @ref LL_DMAMUX_REQ_AES_OUT + * @arg @ref LL_DMAMUX_REQ_HASH_IN + */ +__STATIC_INLINE uint32_t LL_DMA_GetPeriphRequest(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dmamux_ccr_offset = ((((uint32_t)DMAx ^ (uint32_t)DMA1) >> 10U) * 7U); + return (READ_BIT((DMAMUX1_Channel0 + Channel + dmamux_ccr_offset)->CCR, DMAMUX_CxCR_DMAREQ_ID)); +} + +#else +/** + * @brief Set DMA request for DMA instance on Channel x. + * @note Please refer to Reference Manual to get the available mapping of Request value link to Channel Selection. + * @rmtoll CSELR C1S LL_DMA_SetPeriphRequest\n + * CSELR C2S LL_DMA_SetPeriphRequest\n + * CSELR C3S LL_DMA_SetPeriphRequest\n + * CSELR C4S LL_DMA_SetPeriphRequest\n + * CSELR C5S LL_DMA_SetPeriphRequest\n + * CSELR C6S LL_DMA_SetPeriphRequest\n + * CSELR C7S LL_DMA_SetPeriphRequest + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @param PeriphRequest This parameter can be one of the following values: + * @arg @ref LL_DMA_REQUEST_0 + * @arg @ref LL_DMA_REQUEST_1 + * @arg @ref LL_DMA_REQUEST_2 + * @arg @ref LL_DMA_REQUEST_3 + * @arg @ref LL_DMA_REQUEST_4 + * @arg @ref LL_DMA_REQUEST_5 + * @arg @ref LL_DMA_REQUEST_6 + * @arg @ref LL_DMA_REQUEST_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_SetPeriphRequest(DMA_TypeDef *DMAx, uint32_t Channel, uint32_t PeriphRequest) +{ + MODIFY_REG(((DMA_Request_TypeDef *)((uint32_t)((uint32_t)DMAx + DMA_CSELR_OFFSET)))->CSELR, + DMA_CSELR_C1S << ((Channel) * 4U), PeriphRequest << DMA_POSITION_CSELR_CXS); +} + +/** + * @brief Get DMA request for DMA instance on Channel x. + * @rmtoll CSELR C1S LL_DMA_GetPeriphRequest\n + * CSELR C2S LL_DMA_GetPeriphRequest\n + * CSELR C3S LL_DMA_GetPeriphRequest\n + * CSELR C4S LL_DMA_GetPeriphRequest\n + * CSELR C5S LL_DMA_GetPeriphRequest\n + * CSELR C6S LL_DMA_GetPeriphRequest\n + * CSELR C7S LL_DMA_GetPeriphRequest + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA_REQUEST_0 + * @arg @ref LL_DMA_REQUEST_1 + * @arg @ref LL_DMA_REQUEST_2 + * @arg @ref LL_DMA_REQUEST_3 + * @arg @ref LL_DMA_REQUEST_4 + * @arg @ref LL_DMA_REQUEST_5 + * @arg @ref LL_DMA_REQUEST_6 + * @arg @ref LL_DMA_REQUEST_7 + */ +__STATIC_INLINE uint32_t LL_DMA_GetPeriphRequest(DMA_TypeDef *DMAx, uint32_t Channel) +{ + return (READ_BIT(((DMA_Request_TypeDef *)((uint32_t)((uint32_t)DMAx + DMA_CSELR_OFFSET)))->CSELR, + DMA_CSELR_C1S << ((Channel) * 4U)) >> DMA_POSITION_CSELR_CXS); +} + +#endif /* DMAMUX1 */ +/** + * @} + */ + +/** @defgroup DMA_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Get Channel 1 global interrupt flag. + * @rmtoll ISR GIF1 LL_DMA_IsActiveFlag_GI1 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI1(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF1) == (DMA_ISR_GIF1)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 2 global interrupt flag. + * @rmtoll ISR GIF2 LL_DMA_IsActiveFlag_GI2 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI2(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF2) == (DMA_ISR_GIF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 3 global interrupt flag. + * @rmtoll ISR GIF3 LL_DMA_IsActiveFlag_GI3 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI3(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF3) == (DMA_ISR_GIF3)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 4 global interrupt flag. + * @rmtoll ISR GIF4 LL_DMA_IsActiveFlag_GI4 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI4(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF4) == (DMA_ISR_GIF4)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 5 global interrupt flag. + * @rmtoll ISR GIF5 LL_DMA_IsActiveFlag_GI5 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI5(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF5) == (DMA_ISR_GIF5)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 6 global interrupt flag. + * @rmtoll ISR GIF6 LL_DMA_IsActiveFlag_GI6 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI6(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF6) == (DMA_ISR_GIF6)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 7 global interrupt flag. + * @rmtoll ISR GIF7 LL_DMA_IsActiveFlag_GI7 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_GI7(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_GIF7) == (DMA_ISR_GIF7)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 1 transfer complete flag. + * @rmtoll ISR TCIF1 LL_DMA_IsActiveFlag_TC1 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC1(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF1) == (DMA_ISR_TCIF1)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 2 transfer complete flag. + * @rmtoll ISR TCIF2 LL_DMA_IsActiveFlag_TC2 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC2(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF2) == (DMA_ISR_TCIF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 3 transfer complete flag. + * @rmtoll ISR TCIF3 LL_DMA_IsActiveFlag_TC3 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC3(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF3) == (DMA_ISR_TCIF3)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 4 transfer complete flag. + * @rmtoll ISR TCIF4 LL_DMA_IsActiveFlag_TC4 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC4(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF4) == (DMA_ISR_TCIF4)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 5 transfer complete flag. + * @rmtoll ISR TCIF5 LL_DMA_IsActiveFlag_TC5 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC5(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF5) == (DMA_ISR_TCIF5)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 6 transfer complete flag. + * @rmtoll ISR TCIF6 LL_DMA_IsActiveFlag_TC6 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC6(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF6) == (DMA_ISR_TCIF6)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 7 transfer complete flag. + * @rmtoll ISR TCIF7 LL_DMA_IsActiveFlag_TC7 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TC7(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TCIF7) == (DMA_ISR_TCIF7)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 1 half transfer flag. + * @rmtoll ISR HTIF1 LL_DMA_IsActiveFlag_HT1 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT1(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF1) == (DMA_ISR_HTIF1)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 2 half transfer flag. + * @rmtoll ISR HTIF2 LL_DMA_IsActiveFlag_HT2 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT2(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF2) == (DMA_ISR_HTIF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 3 half transfer flag. + * @rmtoll ISR HTIF3 LL_DMA_IsActiveFlag_HT3 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT3(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF3) == (DMA_ISR_HTIF3)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 4 half transfer flag. + * @rmtoll ISR HTIF4 LL_DMA_IsActiveFlag_HT4 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT4(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF4) == (DMA_ISR_HTIF4)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 5 half transfer flag. + * @rmtoll ISR HTIF5 LL_DMA_IsActiveFlag_HT5 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT5(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF5) == (DMA_ISR_HTIF5)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 6 half transfer flag. + * @rmtoll ISR HTIF6 LL_DMA_IsActiveFlag_HT6 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT6(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF6) == (DMA_ISR_HTIF6)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 7 half transfer flag. + * @rmtoll ISR HTIF7 LL_DMA_IsActiveFlag_HT7 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_HT7(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_HTIF7) == (DMA_ISR_HTIF7)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 1 transfer error flag. + * @rmtoll ISR TEIF1 LL_DMA_IsActiveFlag_TE1 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE1(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF1) == (DMA_ISR_TEIF1)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 2 transfer error flag. + * @rmtoll ISR TEIF2 LL_DMA_IsActiveFlag_TE2 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE2(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF2) == (DMA_ISR_TEIF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 3 transfer error flag. + * @rmtoll ISR TEIF3 LL_DMA_IsActiveFlag_TE3 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE3(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF3) == (DMA_ISR_TEIF3)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 4 transfer error flag. + * @rmtoll ISR TEIF4 LL_DMA_IsActiveFlag_TE4 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE4(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF4) == (DMA_ISR_TEIF4)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 5 transfer error flag. + * @rmtoll ISR TEIF5 LL_DMA_IsActiveFlag_TE5 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE5(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF5) == (DMA_ISR_TEIF5)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 6 transfer error flag. + * @rmtoll ISR TEIF6 LL_DMA_IsActiveFlag_TE6 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE6(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF6) == (DMA_ISR_TEIF6)) ? 1UL : 0UL); +} + +/** + * @brief Get Channel 7 transfer error flag. + * @rmtoll ISR TEIF7 LL_DMA_IsActiveFlag_TE7 + * @param DMAx DMAx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsActiveFlag_TE7(DMA_TypeDef *DMAx) +{ + return ((READ_BIT(DMAx->ISR, DMA_ISR_TEIF7) == (DMA_ISR_TEIF7)) ? 1UL : 0UL); +} + +/** + * @brief Clear Channel 1 global interrupt flag. + * @note Do not Clear Channel 1 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC1, LL_DMA_ClearFlag_HT1, + LL_DMA_ClearFlag_TE1. bug 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF1 LL_DMA_ClearFlag_GI1 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI1(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF1); +} + +/** + * @brief Clear Channel 2 global interrupt flag. + * @note Do not Clear Channel 2 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC2, LL_DMA_ClearFlag_HT2, + LL_DMA_ClearFlag_TE2. bug id 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF2 LL_DMA_ClearFlag_GI2 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI2(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF2); +} + +/** + * @brief Clear Channel 3 global interrupt flag. + * @note Do not Clear Channel 3 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC3, LL_DMA_ClearFlag_HT3, + LL_DMA_ClearFlag_TE3. bug id 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF3 LL_DMA_ClearFlag_GI3 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI3(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF3); +} + +/** + * @brief Clear Channel 4 global interrupt flag. + * @note Do not Clear Channel 4 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC4, LL_DMA_ClearFlag_HT4, + LL_DMA_ClearFlag_TE4. bug id 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF4 LL_DMA_ClearFlag_GI4 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI4(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF4); +} + +/** + * @brief Clear Channel 5 global interrupt flag. + * @note Do not Clear Channel 5 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC5, LL_DMA_ClearFlag_HT5, + LL_DMA_ClearFlag_TE5. bug id 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF5 LL_DMA_ClearFlag_GI5 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI5(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF5); +} + +/** + * @brief Clear Channel 6 global interrupt flag. + * @note Do not Clear Channel 6 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC6, LL_DMA_ClearFlag_HT6, + LL_DMA_ClearFlag_TE6. bug id 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF6 LL_DMA_ClearFlag_GI6 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI6(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF6); +} + +/** + * @brief Clear Channel 7 global interrupt flag. + * @note Do not Clear Channel 7 global interrupt flag when the channel in ON. + Instead clear specific flags transfer complete, half transfer & transfer + error flag with LL_DMA_ClearFlag_TC7, LL_DMA_ClearFlag_HT7, + LL_DMA_ClearFlag_TE7. bug id 2.4.1/2.5.1 in Product Errata Sheet. + * @rmtoll IFCR CGIF7 LL_DMA_ClearFlag_GI7 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_GI7(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CGIF7); +} + +/** + * @brief Clear Channel 1 transfer complete flag. + * @rmtoll IFCR CTCIF1 LL_DMA_ClearFlag_TC1 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC1(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF1); +} + +/** + * @brief Clear Channel 2 transfer complete flag. + * @rmtoll IFCR CTCIF2 LL_DMA_ClearFlag_TC2 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC2(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF2); +} + +/** + * @brief Clear Channel 3 transfer complete flag. + * @rmtoll IFCR CTCIF3 LL_DMA_ClearFlag_TC3 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC3(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF3); +} + +/** + * @brief Clear Channel 4 transfer complete flag. + * @rmtoll IFCR CTCIF4 LL_DMA_ClearFlag_TC4 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC4(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF4); +} + +/** + * @brief Clear Channel 5 transfer complete flag. + * @rmtoll IFCR CTCIF5 LL_DMA_ClearFlag_TC5 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC5(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF5); +} + +/** + * @brief Clear Channel 6 transfer complete flag. + * @rmtoll IFCR CTCIF6 LL_DMA_ClearFlag_TC6 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC6(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF6); +} + +/** + * @brief Clear Channel 7 transfer complete flag. + * @rmtoll IFCR CTCIF7 LL_DMA_ClearFlag_TC7 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TC7(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTCIF7); +} + +/** + * @brief Clear Channel 1 half transfer flag. + * @rmtoll IFCR CHTIF1 LL_DMA_ClearFlag_HT1 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT1(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF1); +} + +/** + * @brief Clear Channel 2 half transfer flag. + * @rmtoll IFCR CHTIF2 LL_DMA_ClearFlag_HT2 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT2(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF2); +} + +/** + * @brief Clear Channel 3 half transfer flag. + * @rmtoll IFCR CHTIF3 LL_DMA_ClearFlag_HT3 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT3(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF3); +} + +/** + * @brief Clear Channel 4 half transfer flag. + * @rmtoll IFCR CHTIF4 LL_DMA_ClearFlag_HT4 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT4(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF4); +} + +/** + * @brief Clear Channel 5 half transfer flag. + * @rmtoll IFCR CHTIF5 LL_DMA_ClearFlag_HT5 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT5(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF5); +} + +/** + * @brief Clear Channel 6 half transfer flag. + * @rmtoll IFCR CHTIF6 LL_DMA_ClearFlag_HT6 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT6(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF6); +} + +/** + * @brief Clear Channel 7 half transfer flag. + * @rmtoll IFCR CHTIF7 LL_DMA_ClearFlag_HT7 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_HT7(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CHTIF7); +} + +/** + * @brief Clear Channel 1 transfer error flag. + * @rmtoll IFCR CTEIF1 LL_DMA_ClearFlag_TE1 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE1(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF1); +} + +/** + * @brief Clear Channel 2 transfer error flag. + * @rmtoll IFCR CTEIF2 LL_DMA_ClearFlag_TE2 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE2(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF2); +} + +/** + * @brief Clear Channel 3 transfer error flag. + * @rmtoll IFCR CTEIF3 LL_DMA_ClearFlag_TE3 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE3(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF3); +} + +/** + * @brief Clear Channel 4 transfer error flag. + * @rmtoll IFCR CTEIF4 LL_DMA_ClearFlag_TE4 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE4(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF4); +} + +/** + * @brief Clear Channel 5 transfer error flag. + * @rmtoll IFCR CTEIF5 LL_DMA_ClearFlag_TE5 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE5(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF5); +} + +/** + * @brief Clear Channel 6 transfer error flag. + * @rmtoll IFCR CTEIF6 LL_DMA_ClearFlag_TE6 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE6(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF6); +} + +/** + * @brief Clear Channel 7 transfer error flag. + * @rmtoll IFCR CTEIF7 LL_DMA_ClearFlag_TE7 + * @param DMAx DMAx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA_ClearFlag_TE7(DMA_TypeDef *DMAx) +{ + WRITE_REG(DMAx->IFCR, DMA_IFCR_CTEIF7); +} + +/** + * @} + */ + +/** @defgroup DMA_LL_EF_IT_Management IT_Management + * @{ + */ +/** + * @brief Enable Transfer complete interrupt. + * @rmtoll CCR TCIE LL_DMA_EnableIT_TC + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_EnableIT_TC(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + SET_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_TCIE); +} + +/** + * @brief Enable Half transfer interrupt. + * @rmtoll CCR HTIE LL_DMA_EnableIT_HT + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_EnableIT_HT(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + SET_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_HTIE); +} + +/** + * @brief Enable Transfer error interrupt. + * @rmtoll CCR TEIE LL_DMA_EnableIT_TE + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_EnableIT_TE(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + SET_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_TEIE); +} + +/** + * @brief Disable Transfer complete interrupt. + * @rmtoll CCR TCIE LL_DMA_DisableIT_TC + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_DisableIT_TC(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + CLEAR_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_TCIE); +} + +/** + * @brief Disable Half transfer interrupt. + * @rmtoll CCR HTIE LL_DMA_DisableIT_HT + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_DisableIT_HT(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + CLEAR_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_HTIE); +} + +/** + * @brief Disable Transfer error interrupt. + * @rmtoll CCR TEIE LL_DMA_DisableIT_TE + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval None + */ +__STATIC_INLINE void LL_DMA_DisableIT_TE(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + CLEAR_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, DMA_CCR_TEIE); +} + +/** + * @brief Check if Transfer complete Interrupt is enabled. + * @rmtoll CCR TCIE LL_DMA_IsEnabledIT_TC + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsEnabledIT_TC(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return ((READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_TCIE) == (DMA_CCR_TCIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Half transfer Interrupt is enabled. + * @rmtoll CCR HTIE LL_DMA_IsEnabledIT_HT + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsEnabledIT_HT(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return ((READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_HTIE) == (DMA_CCR_HTIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Transfer error Interrupt is enabled. + * @rmtoll CCR TEIE LL_DMA_IsEnabledIT_TE + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA_IsEnabledIT_TE(DMA_TypeDef *DMAx, uint32_t Channel) +{ + uint32_t dma_base_addr = (uint32_t)DMAx; + return ((READ_BIT(((DMA_Channel_TypeDef *)(dma_base_addr + CHANNEL_OFFSET_TAB[Channel]))->CCR, + DMA_CCR_TEIE) == (DMA_CCR_TEIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DMA_LL_EF_Init Initialization and de-initialization functions + * @{ + */ +ErrorStatus LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct); +ErrorStatus LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel); +void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMA1 || DMA2 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_DMA_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dmamux.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dmamux.h new file mode 100644 index 0000000..1cf26f2 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_dmamux.h @@ -0,0 +1,1981 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_dmamux.h + * @author MCD Application Team + * @brief Header file of DMAMUX 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 STM32L4xx_LL_DMAMUX_H +#define STM32L4xx_LL_DMAMUX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (DMAMUX1) + +/** @defgroup DMAMUX_LL DMAMUX + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup DMAMUX_LL_Private_Constants DMAMUX Private Constants + * @{ + */ +/* Define used to get DMAMUX CCR register size */ +#define DMAMUX_CCR_SIZE 0x00000004UL + +/* Define used to get DMAMUX RGCR register size */ +#define DMAMUX_RGCR_SIZE 0x00000004UL +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DMAMUX_LL_Exported_Constants DMAMUX Exported Constants + * @{ + */ +/** @defgroup DMAMUX_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_DMAMUX_WriteReg function + * @{ + */ +#define LL_DMAMUX_CFR_CSOF0 DMAMUX_CFR_CSOF0 /*!< Synchronization Event Overrun Flag Channel 0 */ +#define LL_DMAMUX_CFR_CSOF1 DMAMUX_CFR_CSOF1 /*!< Synchronization Event Overrun Flag Channel 1 */ +#define LL_DMAMUX_CFR_CSOF2 DMAMUX_CFR_CSOF2 /*!< Synchronization Event Overrun Flag Channel 2 */ +#define LL_DMAMUX_CFR_CSOF3 DMAMUX_CFR_CSOF3 /*!< Synchronization Event Overrun Flag Channel 3 */ +#define LL_DMAMUX_CFR_CSOF4 DMAMUX_CFR_CSOF4 /*!< Synchronization Event Overrun Flag Channel 4 */ +#define LL_DMAMUX_CFR_CSOF5 DMAMUX_CFR_CSOF5 /*!< Synchronization Event Overrun Flag Channel 5 */ +#define LL_DMAMUX_CFR_CSOF6 DMAMUX_CFR_CSOF6 /*!< Synchronization Event Overrun Flag Channel 6 */ +#define LL_DMAMUX_CFR_CSOF7 DMAMUX_CFR_CSOF7 /*!< Synchronization Event Overrun Flag Channel 7 */ +#define LL_DMAMUX_CFR_CSOF8 DMAMUX_CFR_CSOF8 /*!< Synchronization Event Overrun Flag Channel 8 */ +#define LL_DMAMUX_CFR_CSOF9 DMAMUX_CFR_CSOF9 /*!< Synchronization Event Overrun Flag Channel 9 */ +#define LL_DMAMUX_CFR_CSOF10 DMAMUX_CFR_CSOF10 /*!< Synchronization Event Overrun Flag Channel 10 */ +#define LL_DMAMUX_CFR_CSOF11 DMAMUX_CFR_CSOF11 /*!< Synchronization Event Overrun Flag Channel 11 */ +#define LL_DMAMUX_CFR_CSOF12 DMAMUX_CFR_CSOF12 /*!< Synchronization Event Overrun Flag Channel 12 */ +#define LL_DMAMUX_CFR_CSOF13 DMAMUX_CFR_CSOF13 /*!< Synchronization Event Overrun Flag Channel 13 */ +#define LL_DMAMUX_RGCFR_RGCOF0 DMAMUX_RGCFR_COF0 /*!< Request Generator 0 Trigger Event Overrun Flag */ +#define LL_DMAMUX_RGCFR_RGCOF1 DMAMUX_RGCFR_COF1 /*!< Request Generator 1 Trigger Event Overrun Flag */ +#define LL_DMAMUX_RGCFR_RGCOF2 DMAMUX_RGCFR_COF2 /*!< Request Generator 2 Trigger Event Overrun Flag */ +#define LL_DMAMUX_RGCFR_RGCOF3 DMAMUX_RGCFR_COF3 /*!< Request Generator 3 Trigger Event Overrun Flag */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_DMAMUX_ReadReg function + * @{ + */ +#define LL_DMAMUX_CSR_SOF0 DMAMUX_CSR_SOF0 /*!< Synchronization Event Overrun Flag Channel 0 */ +#define LL_DMAMUX_CSR_SOF1 DMAMUX_CSR_SOF1 /*!< Synchronization Event Overrun Flag Channel 1 */ +#define LL_DMAMUX_CSR_SOF2 DMAMUX_CSR_SOF2 /*!< Synchronization Event Overrun Flag Channel 2 */ +#define LL_DMAMUX_CSR_SOF3 DMAMUX_CSR_SOF3 /*!< Synchronization Event Overrun Flag Channel 3 */ +#define LL_DMAMUX_CSR_SOF4 DMAMUX_CSR_SOF4 /*!< Synchronization Event Overrun Flag Channel 4 */ +#define LL_DMAMUX_CSR_SOF5 DMAMUX_CSR_SOF5 /*!< Synchronization Event Overrun Flag Channel 5 */ +#define LL_DMAMUX_CSR_SOF6 DMAMUX_CSR_SOF6 /*!< Synchronization Event Overrun Flag Channel 6 */ +#define LL_DMAMUX_CSR_SOF7 DMAMUX_CSR_SOF7 /*!< Synchronization Event Overrun Flag Channel 7 */ +#define LL_DMAMUX_CSR_SOF8 DMAMUX_CSR_SOF8 /*!< Synchronization Event Overrun Flag Channel 8 */ +#define LL_DMAMUX_CSR_SOF9 DMAMUX_CSR_SOF9 /*!< Synchronization Event Overrun Flag Channel 9 */ +#define LL_DMAMUX_CSR_SOF10 DMAMUX_CSR_SOF10 /*!< Synchronization Event Overrun Flag Channel 10 */ +#define LL_DMAMUX_CSR_SOF11 DMAMUX_CSR_SOF11 /*!< Synchronization Event Overrun Flag Channel 11 */ +#define LL_DMAMUX_CSR_SOF12 DMAMUX_CSR_SOF12 /*!< Synchronization Event Overrun Flag Channel 12 */ +#define LL_DMAMUX_CSR_SOF13 DMAMUX_CSR_SOF13 /*!< Synchronization Event Overrun Flag Channel 13 */ +#define LL_DMAMUX_RGSR_RGOF0 DMAMUX_RGSR_OF0 /*!< Request Generator 0 Trigger Event Overrun Flag */ +#define LL_DMAMUX_RGSR_RGOF1 DMAMUX_RGSR_OF1 /*!< Request Generator 1 Trigger Event Overrun Flag */ +#define LL_DMAMUX_RGSR_RGOF2 DMAMUX_RGSR_OF2 /*!< Request Generator 2 Trigger Event Overrun Flag */ +#define LL_DMAMUX_RGSR_RGOF3 DMAMUX_RGSR_OF3 /*!< Request Generator 3 Trigger Event Overrun Flag */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_DMA_ReadReg and LL_DMAMUX_WriteReg functions + * @{ + */ +#define LL_DMAMUX_CCR_SOIE DMAMUX_CxCR_SOIE /*!< Synchronization Event Overrun Interrupt */ +#define LL_DMAMUX_RGCR_RGOIE DMAMUX_RGxCR_OIE /*!< Request Generation Trigger Event Overrun Interrupt */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_REQUEST Transfer request + * @{ + */ +#define LL_DMAMUX_REQ_MEM2MEM 0U /*!< Memory to memory transfer */ + +#define LL_DMAMUX_REQ_GENERATOR0 1U /*!< DMAMUX request generator 0 */ +#define LL_DMAMUX_REQ_GENERATOR1 2U /*!< DMAMUX request generator 1 */ +#define LL_DMAMUX_REQ_GENERATOR2 3U /*!< DMAMUX request generator 2 */ +#define LL_DMAMUX_REQ_GENERATOR3 4U /*!< DMAMUX request generator 3 */ + +#define LL_DMAMUX_REQ_ADC1 5U /*!< DMAMUX ADC1 request */ + +#if defined (ADC2) + +#define LL_DMAMUX_REQ_ADC2 6U /*!< DMAMUX ADC1 request */ + +#define LL_DMAMUX_REQ_DAC1_CH1 7U /*!< DMAMUX DAC1 CH1 request */ +#define LL_DMAMUX_REQ_DAC1_CH2 8U /*!< DMAMUX DAC1 CH2 request */ + +#define LL_DMAMUX_REQ_TIM6_UP 9U /*!< DMAMUX TIM6 UP request */ +#define LL_DMAMUX_REQ_TIM7_UP 10U /*!< DMAMUX TIM7 UP request */ + +#define LL_DMAMUX_REQ_SPI1_RX 11U /*!< DMAMUX SPI1 RX request */ +#define LL_DMAMUX_REQ_SPI1_TX 12U /*!< DMAMUX SPI1 TX request */ +#define LL_DMAMUX_REQ_SPI2_RX 13U /*!< DMAMUX SPI2 RX request */ +#define LL_DMAMUX_REQ_SPI2_TX 14U /*!< DMAMUX SPI2 TX request */ +#define LL_DMAMUX_REQ_SPI3_RX 15U /*!< DMAMUX SPI3 RX request */ +#define LL_DMAMUX_REQ_SPI3_TX 16U /*!< DMAMUX SPI3 TX request */ + +#define LL_DMAMUX_REQ_I2C1_RX 17U /*!< DMAMUX I2C1 RX request */ +#define LL_DMAMUX_REQ_I2C1_TX 18U /*!< DMAMUX I2C1 TX request */ +#define LL_DMAMUX_REQ_I2C2_RX 19U /*!< DMAMUX I2C2 RX request */ +#define LL_DMAMUX_REQ_I2C2_TX 20U /*!< DMAMUX I2C2 TX request */ +#define LL_DMAMUX_REQ_I2C3_RX 21U /*!< DMAMUX I2C3 RX request */ +#define LL_DMAMUX_REQ_I2C3_TX 22U /*!< DMAMUX I2C3 TX request */ +#define LL_DMAMUX_REQ_I2C4_RX 23U /*!< DMAMUX I2C4 RX request */ +#define LL_DMAMUX_REQ_I2C4_TX 24U /*!< DMAMUX I2C4 TX request */ + +#define LL_DMAMUX_REQ_USART1_RX 25U /*!< DMAMUX USART1 RX request */ +#define LL_DMAMUX_REQ_USART1_TX 26U /*!< DMAMUX USART1 TX request */ +#define LL_DMAMUX_REQ_USART2_RX 27U /*!< DMAMUX USART2 RX request */ +#define LL_DMAMUX_REQ_USART2_TX 28U /*!< DMAMUX USART2 TX request */ +#define LL_DMAMUX_REQ_USART3_RX 29U /*!< DMAMUX USART3 RX request */ +#define LL_DMAMUX_REQ_USART3_TX 30U /*!< DMAMUX USART3 TX request */ + +#define LL_DMAMUX_REQ_UART4_RX 31U /*!< DMAMUX UART4 RX request */ +#define LL_DMAMUX_REQ_UART4_TX 32U /*!< DMAMUX UART4 TX request */ +#define LL_DMAMUX_REQ_UART5_RX 33U /*!< DMAMUX UART5 RX request */ +#define LL_DMAMUX_REQ_UART5_TX 34U /*!< DMAMUX UART5 TX request */ + +#define LL_DMAMUX_REQ_LPUART1_RX 35U /*!< DMAMUX LPUART1 RX request */ +#define LL_DMAMUX_REQ_LPUART1_TX 36U /*!< DMAMUX LPUART1 TX request */ + +#define LL_DMAMUX_REQ_SAI1_A 37U /*!< DMAMUX SAI1 A request */ +#define LL_DMAMUX_REQ_SAI1_B 38U /*!< DMAMUX SAI1 B request */ +#define LL_DMAMUX_REQ_SAI2_A 39U /*!< DMAMUX SAI2 A request */ +#define LL_DMAMUX_REQ_SAI2_B 40U /*!< DMAMUX SAI2 B request */ + +#define LL_DMAMUX_REQ_OSPI1 41U /*!< DMAMUX OCTOSPI1 request */ +#define LL_DMAMUX_REQ_OSPI2 42U /*!< DMAMUX OCTOSPI2 request */ + +#define LL_DMAMUX_REQ_TIM1_CH1 43U /*!< DMAMUX TIM1 CH1 request */ +#define LL_DMAMUX_REQ_TIM1_CH2 44U /*!< DMAMUX TIM1 CH2 request */ +#define LL_DMAMUX_REQ_TIM1_CH3 45U /*!< DMAMUX TIM1 CH3 request */ +#define LL_DMAMUX_REQ_TIM1_CH4 46U /*!< DMAMUX TIM1 CH4 request */ +#define LL_DMAMUX_REQ_TIM1_UP 47U /*!< DMAMUX TIM1 UP request */ +#define LL_DMAMUX_REQ_TIM1_TRIG 48U /*!< DMAMUX TIM1 TRIG request */ +#define LL_DMAMUX_REQ_TIM1_COM 49U /*!< DMAMUX TIM1 COM request */ + +#define LL_DMAMUX_REQ_TIM8_CH1 50U /*!< DMAMUX TIM8 CH1 request */ +#define LL_DMAMUX_REQ_TIM8_CH2 51U /*!< DMAMUX TIM8 CH2 request */ +#define LL_DMAMUX_REQ_TIM8_CH3 52U /*!< DMAMUX TIM8 CH3 request */ +#define LL_DMAMUX_REQ_TIM8_CH4 53U /*!< DMAMUX TIM8 CH4 request */ +#define LL_DMAMUX_REQ_TIM8_UP 54U /*!< DMAMUX TIM8 UP request */ +#define LL_DMAMUX_REQ_TIM8_TRIG 55U /*!< DMAMUX TIM8 TRIG request */ +#define LL_DMAMUX_REQ_TIM8_COM 56U /*!< DMAMUX TIM8 COM request */ + +#define LL_DMAMUX_REQ_TIM2_CH1 57U /*!< DMAMUX TIM2 CH1 request */ +#define LL_DMAMUX_REQ_TIM2_CH2 58U /*!< DMAMUX TIM2 CH2 request */ +#define LL_DMAMUX_REQ_TIM2_CH3 59U /*!< DMAMUX TIM2 CH3 request */ +#define LL_DMAMUX_REQ_TIM2_CH4 60U /*!< DMAMUX TIM2 CH4 request */ +#define LL_DMAMUX_REQ_TIM2_UP 61U /*!< DMAMUX TIM2 UP request */ + +#define LL_DMAMUX_REQ_TIM3_CH1 62U /*!< DMAMUX TIM3 CH1 request */ +#define LL_DMAMUX_REQ_TIM3_CH2 63U /*!< DMAMUX TIM3 CH2 request */ +#define LL_DMAMUX_REQ_TIM3_CH3 64U /*!< DMAMUX TIM3 CH3 request */ +#define LL_DMAMUX_REQ_TIM3_CH4 65U /*!< DMAMUX TIM3 CH4 request */ +#define LL_DMAMUX_REQ_TIM3_UP 66U /*!< DMAMUX TIM3 UP request */ +#define LL_DMAMUX_REQ_TIM3_TRIG 67U /*!< DMAMUX TIM3 TRIG request */ + +#define LL_DMAMUX_REQ_TIM4_CH1 68U /*!< DMAMUX TIM4 CH1 request */ +#define LL_DMAMUX_REQ_TIM4_CH2 69U /*!< DMAMUX TIM4 CH2 request */ +#define LL_DMAMUX_REQ_TIM4_CH3 70U /*!< DMAMUX TIM4 CH3 request */ +#define LL_DMAMUX_REQ_TIM4_CH4 71U /*!< DMAMUX TIM4 CH4 request */ +#define LL_DMAMUX_REQ_TIM4_UP 72U /*!< DMAMUX TIM4 UP request */ + +#define LL_DMAMUX_REQ_TIM5_CH1 73U /*!< DMAMUX TIM5 CH1 request */ +#define LL_DMAMUX_REQ_TIM5_CH2 74U /*!< DMAMUX TIM5 CH2 request */ +#define LL_DMAMUX_REQ_TIM5_CH3 75U /*!< DMAMUX TIM5 CH3 request */ +#define LL_DMAMUX_REQ_TIM5_CH4 76U /*!< DMAMUX TIM5 CH4 request */ +#define LL_DMAMUX_REQ_TIM5_UP 77U /*!< DMAMUX TIM5 UP request */ +#define LL_DMAMUX_REQ_TIM5_TRIG 78U /*!< DMAMUX TIM5 TRIG request */ +#define LL_DMAMUX_REQ_TIM15_CH1 79U /*!< DMAMUX TIM15 CH1 request */ +#define LL_DMAMUX_REQ_TIM15_UP 80U /*!< DMAMUX TIM15 UP request */ +#define LL_DMAMUX_REQ_TIM15_TRIG 81U /*!< DMAMUX TIM15 TRIG request */ +#define LL_DMAMUX_REQ_TIM15_COM 82U /*!< DMAMUX TIM15 COM request */ + +#define LL_DMAMUX_REQ_TIM16_CH1 83U /*!< DMAMUX TIM16 CH1 request */ +#define LL_DMAMUX_REQ_TIM16_UP 84U /*!< DMAMUX TIM16 UP request */ +#define LL_DMAMUX_REQ_TIM17_CH1 85U /*!< DMAMUX TIM17 CH1 request */ +#define LL_DMAMUX_REQ_TIM17_UP 86U /*!< DMAMUX TIM17 UP request */ + +#define LL_DMAMUX_REQ_DFSDM1_FLT0 87U /*!< DMAMUX DFSDM1_FLT0 request */ +#define LL_DMAMUX_REQ_DFSDM1_FLT1 88U /*!< DMAMUX DFSDM1_FLT1 request */ +#define LL_DMAMUX_REQ_DFSDM1_FLT2 89U /*!< DMAMUX DFSDM1_FLT2 request */ +#define LL_DMAMUX_REQ_DFSDM1_FLT3 90U /*!< DMAMUX DFSDM1_FLT3 request */ + +#define LL_DMAMUX_REQ_DCMI 91U /*!< DMAMUX DCMI request */ +#define LL_DMAMUX_REQ_DCMI_PSSI 91U /*!< DMAMUX PSSI request */ + +#define LL_DMAMUX_REQ_AES_IN 92U /*!< DMAMUX AES_IN request */ +#define LL_DMAMUX_REQ_AES_OUT 93U /*!< DMAMUX AES_OUT request */ + +#define LL_DMAMUX_REQ_HASH_IN 94U /*!< DMAMUX HASH_IN request */ + +#else + +#define LL_DMAMUX_REQ_DAC1_CH1 6U /*!< DMAMUX DAC1 CH1 request */ +#define LL_DMAMUX_REQ_DAC1_CH2 7U /*!< DMAMUX DAC1 CH2 request */ + +#define LL_DMAMUX_REQ_TIM6_UP 8U /*!< DMAMUX TIM6 UP request */ +#define LL_DMAMUX_REQ_TIM7_UP 9U /*!< DMAMUX TIM7 UP request */ + +#define LL_DMAMUX_REQ_SPI1_RX 10U /*!< DMAMUX SPI1 RX request */ +#define LL_DMAMUX_REQ_SPI1_TX 11U /*!< DMAMUX SPI1 TX request */ +#define LL_DMAMUX_REQ_SPI2_RX 12U /*!< DMAMUX SPI2 RX request */ +#define LL_DMAMUX_REQ_SPI2_TX 13U /*!< DMAMUX SPI2 TX request */ +#define LL_DMAMUX_REQ_SPI3_RX 14U /*!< DMAMUX SPI3 RX request */ +#define LL_DMAMUX_REQ_SPI3_TX 15U /*!< DMAMUX SPI3 TX request */ + +#define LL_DMAMUX_REQ_I2C1_RX 16U /*!< DMAMUX I2C1 RX request */ +#define LL_DMAMUX_REQ_I2C1_TX 17U /*!< DMAMUX I2C1 TX request */ +#define LL_DMAMUX_REQ_I2C2_RX 18U /*!< DMAMUX I2C2 RX request */ +#define LL_DMAMUX_REQ_I2C2_TX 19U /*!< DMAMUX I2C2 TX request */ +#define LL_DMAMUX_REQ_I2C3_RX 20U /*!< DMAMUX I2C3 RX request */ +#define LL_DMAMUX_REQ_I2C3_TX 21U /*!< DMAMUX I2C3 TX request */ +#define LL_DMAMUX_REQ_I2C4_RX 22U /*!< DMAMUX I2C4 RX request */ +#define LL_DMAMUX_REQ_I2C4_TX 23U /*!< DMAMUX I2C4 TX request */ + +#define LL_DMAMUX_REQ_USART1_RX 24U /*!< DMAMUX USART1 RX request */ +#define LL_DMAMUX_REQ_USART1_TX 25U /*!< DMAMUX USART1 TX request */ +#define LL_DMAMUX_REQ_USART2_RX 26U /*!< DMAMUX USART2 RX request */ +#define LL_DMAMUX_REQ_USART2_TX 27U /*!< DMAMUX USART2 TX request */ +#define LL_DMAMUX_REQ_USART3_RX 28U /*!< DMAMUX USART3 RX request */ +#define LL_DMAMUX_REQ_USART3_TX 29U /*!< DMAMUX USART3 TX request */ + +#define LL_DMAMUX_REQ_UART4_RX 30U /*!< DMAMUX UART4 RX request */ +#define LL_DMAMUX_REQ_UART4_TX 31U /*!< DMAMUX UART4 TX request */ +#define LL_DMAMUX_REQ_UART5_RX 32U /*!< DMAMUX UART5 RX request */ +#define LL_DMAMUX_REQ_UART5_TX 33U /*!< DMAMUX UART5 TX request */ + +#define LL_DMAMUX_REQ_LPUART1_RX 34U /*!< DMAMUX LPUART1 RX request */ +#define LL_DMAMUX_REQ_LPUART1_TX 35U /*!< DMAMUX LPUART1 TX request */ + +#define LL_DMAMUX_REQ_SAI1_A 36U /*!< DMAMUX SAI1 A request */ +#define LL_DMAMUX_REQ_SAI1_B 37U /*!< DMAMUX SAI1 B request */ +#define LL_DMAMUX_REQ_SAI2_A 38U /*!< DMAMUX SAI2 A request */ +#define LL_DMAMUX_REQ_SAI2_B 39U /*!< DMAMUX SAI2 B request */ + +#define LL_DMAMUX_REQ_OSPI1 40U /*!< DMAMUX OCTOSPI1 request */ +#define LL_DMAMUX_REQ_OSPI2 41U /*!< DMAMUX OCTOSPI2 request */ + +#define LL_DMAMUX_REQ_TIM1_CH1 42U /*!< DMAMUX TIM1 CH1 request */ +#define LL_DMAMUX_REQ_TIM1_CH2 43U /*!< DMAMUX TIM1 CH2 request */ +#define LL_DMAMUX_REQ_TIM1_CH3 44U /*!< DMAMUX TIM1 CH3 request */ +#define LL_DMAMUX_REQ_TIM1_CH4 45U /*!< DMAMUX TIM1 CH4 request */ +#define LL_DMAMUX_REQ_TIM1_UP 46U /*!< DMAMUX TIM1 UP request */ +#define LL_DMAMUX_REQ_TIM1_TRIG 47U /*!< DMAMUX TIM1 TRIG request */ +#define LL_DMAMUX_REQ_TIM1_COM 48U /*!< DMAMUX TIM1 COM request */ + +#define LL_DMAMUX_REQ_TIM8_CH1 49U /*!< DMAMUX TIM8 CH1 request */ +#define LL_DMAMUX_REQ_TIM8_CH2 50U /*!< DMAMUX TIM8 CH2 request */ +#define LL_DMAMUX_REQ_TIM8_CH3 51U /*!< DMAMUX TIM8 CH3 request */ +#define LL_DMAMUX_REQ_TIM8_CH4 52U /*!< DMAMUX TIM8 CH4 request */ +#define LL_DMAMUX_REQ_TIM8_UP 53U /*!< DMAMUX TIM8 UP request */ +#define LL_DMAMUX_REQ_TIM8_TRIG 54U /*!< DMAMUX TIM8 TRIG request */ +#define LL_DMAMUX_REQ_TIM8_COM 55U /*!< DMAMUX TIM8 COM request */ + +#define LL_DMAMUX_REQ_TIM2_CH1 56U /*!< DMAMUX TIM2 CH1 request */ +#define LL_DMAMUX_REQ_TIM2_CH2 57U /*!< DMAMUX TIM2 CH2 request */ +#define LL_DMAMUX_REQ_TIM2_CH3 58U /*!< DMAMUX TIM2 CH3 request */ +#define LL_DMAMUX_REQ_TIM2_CH4 59U /*!< DMAMUX TIM2 CH4 request */ +#define LL_DMAMUX_REQ_TIM2_UP 60U /*!< DMAMUX TIM2 UP request */ + +#define LL_DMAMUX_REQ_TIM3_CH1 61U /*!< DMAMUX TIM3 CH1 request */ +#define LL_DMAMUX_REQ_TIM3_CH2 62U /*!< DMAMUX TIM3 CH2 request */ +#define LL_DMAMUX_REQ_TIM3_CH3 63U /*!< DMAMUX TIM3 CH3 request */ +#define LL_DMAMUX_REQ_TIM3_CH4 64U /*!< DMAMUX TIM3 CH4 request */ +#define LL_DMAMUX_REQ_TIM3_UP 65U /*!< DMAMUX TIM3 UP request */ +#define LL_DMAMUX_REQ_TIM3_TRIG 66U /*!< DMAMUX TIM3 TRIG request */ + +#define LL_DMAMUX_REQ_TIM4_CH1 67U /*!< DMAMUX TIM4 CH1 request */ +#define LL_DMAMUX_REQ_TIM4_CH2 68U /*!< DMAMUX TIM4 CH2 request */ +#define LL_DMAMUX_REQ_TIM4_CH3 69U /*!< DMAMUX TIM4 CH3 request */ +#define LL_DMAMUX_REQ_TIM4_CH4 70U /*!< DMAMUX TIM4 CH4 request */ +#define LL_DMAMUX_REQ_TIM4_UP 71U /*!< DMAMUX TIM4 UP request */ + +#define LL_DMAMUX_REQ_TIM5_CH1 72U /*!< DMAMUX TIM5 CH1 request */ +#define LL_DMAMUX_REQ_TIM5_CH2 73U /*!< DMAMUX TIM5 CH2 request */ +#define LL_DMAMUX_REQ_TIM5_CH3 74U /*!< DMAMUX TIM5 CH3 request */ +#define LL_DMAMUX_REQ_TIM5_CH4 75U /*!< DMAMUX TIM5 CH4 request */ +#define LL_DMAMUX_REQ_TIM5_UP 76U /*!< DMAMUX TIM5 UP request */ +#define LL_DMAMUX_REQ_TIM5_TRIG 77U /*!< DMAMUX TIM5 TRIG request */ +#define LL_DMAMUX_REQ_TIM15_CH1 78U /*!< DMAMUX TIM15 CH1 request */ +#define LL_DMAMUX_REQ_TIM15_UP 79U /*!< DMAMUX TIM15 UP request */ +#define LL_DMAMUX_REQ_TIM15_TRIG 80U /*!< DMAMUX TIM15 TRIG request */ +#define LL_DMAMUX_REQ_TIM15_COM 81U /*!< DMAMUX TIM15 COM request */ + +#define LL_DMAMUX_REQ_TIM16_CH1 82U /*!< DMAMUX TIM16 CH1 request */ +#define LL_DMAMUX_REQ_TIM16_UP 83U /*!< DMAMUX TIM16 UP request */ +#define LL_DMAMUX_REQ_TIM17_CH1 84U /*!< DMAMUX TIM17 CH1 request */ +#define LL_DMAMUX_REQ_TIM17_UP 85U /*!< DMAMUX TIM17 UP request */ + +#define LL_DMAMUX_REQ_DFSDM1_FLT0 86U /*!< DMAMUX DFSDM1_FLT0 request */ +#define LL_DMAMUX_REQ_DFSDM1_FLT1 87U /*!< DMAMUX DFSDM1_FLT1 request */ +#define LL_DMAMUX_REQ_DFSDM1_FLT2 88U /*!< DMAMUX DFSDM1_FLT2 request */ +#define LL_DMAMUX_REQ_DFSDM1_FLT3 89U /*!< DMAMUX DFSDM1_FLT3 request */ + +#define LL_DMAMUX_REQ_DCMI 90U /*!< DMAMUX DCMI request */ + +#define LL_DMAMUX_REQ_AES_IN 91U /*!< DMAMUX AES_IN request */ +#define LL_DMAMUX_REQ_AES_OUT 92U /*!< DMAMUX AES_OUT request */ + +#define LL_DMAMUX_REQ_HASH_IN 93U /*!< DMAMUX HASH_IN request */ + +#endif + +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_CHANNEL DMAMUX Channel + * @{ + */ +#define LL_DMAMUX_CHANNEL_0 0x00000000U /*!< DMAMUX Channel 0 connected to DMA1 Channel 1 */ +#define LL_DMAMUX_CHANNEL_1 0x00000001U /*!< DMAMUX Channel 1 connected to DMA1 Channel 2 */ +#define LL_DMAMUX_CHANNEL_2 0x00000002U /*!< DMAMUX Channel 2 connected to DMA1 Channel 3 */ +#define LL_DMAMUX_CHANNEL_3 0x00000003U /*!< DMAMUX Channel 3 connected to DMA1 Channel 4 */ +#define LL_DMAMUX_CHANNEL_4 0x00000004U /*!< DMAMUX Channel 4 connected to DMA1 Channel 5 */ +#define LL_DMAMUX_CHANNEL_5 0x00000005U /*!< DMAMUX Channel 5 connected to DMA1 Channel 6 */ +#define LL_DMAMUX_CHANNEL_6 0x00000006U /*!< DMAMUX Channel 6 connected to DMA1 Channel 7 */ +#define LL_DMAMUX_CHANNEL_7 0x00000007U /*!< DMAMUX Channel 7 connected to DMA2 Channel 1 */ +#define LL_DMAMUX_CHANNEL_8 0x00000008U /*!< DMAMUX Channel 8 connected to DMA2 Channel 2 */ +#define LL_DMAMUX_CHANNEL_9 0x00000009U /*!< DMAMUX Channel 9 connected to DMA2 Channel 3 */ +#define LL_DMAMUX_CHANNEL_10 0x0000000AU /*!< DMAMUX Channel 10 connected to DMA2 Channel 4 */ +#define LL_DMAMUX_CHANNEL_11 0x0000000BU /*!< DMAMUX Channel 11 connected to DMA2 Channel 5 */ +#define LL_DMAMUX_CHANNEL_12 0x0000000CU /*!< DMAMUX Channel 12 connected to DMA2 Channel 6 */ +#define LL_DMAMUX_CHANNEL_13 0x0000000DU /*!< DMAMUX Channel 13 connected to DMA2 Channel 7 */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_SYNC_NO Synchronization Signal Polarity + * @{ + */ +#define LL_DMAMUX_SYNC_NO_EVENT 0x00000000U /*!< All requests are blocked */ +#define LL_DMAMUX_SYNC_POL_RISING DMAMUX_CxCR_SPOL_0 /*!< Synchronization on event on rising edge */ +#define LL_DMAMUX_SYNC_POL_FALLING DMAMUX_CxCR_SPOL_1 /*!< Synchronization on event on falling edge */ +#define LL_DMAMUX_SYNC_POL_RISING_FALLING (DMAMUX_CxCR_SPOL_0 | DMAMUX_CxCR_SPOL_1) /*!< Synchronization on event on rising and falling edge */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_SYNC_EVT Synchronization Signal Event + * @{ + */ +#define LL_DMAMUX_SYNC_EXTI_LINE0 0x00000000U /*!< Synchronization signal from EXTI Line0 */ +#define LL_DMAMUX_SYNC_EXTI_LINE1 DMAMUX_CxCR_SYNC_ID_0 /*!< Synchronization signal from EXTI Line1 */ +#define LL_DMAMUX_SYNC_EXTI_LINE2 DMAMUX_CxCR_SYNC_ID_1 /*!< Synchronization signal from EXTI Line2 */ +#define LL_DMAMUX_SYNC_EXTI_LINE3 (DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line3 */ +#define LL_DMAMUX_SYNC_EXTI_LINE4 DMAMUX_CxCR_SYNC_ID_2 /*!< Synchronization signal from EXTI Line4 */ +#define LL_DMAMUX_SYNC_EXTI_LINE5 (DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line5 */ +#define LL_DMAMUX_SYNC_EXTI_LINE6 (DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_1) /*!< Synchronization signal from EXTI Line6 */ +#define LL_DMAMUX_SYNC_EXTI_LINE7 (DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line7 */ +#define LL_DMAMUX_SYNC_EXTI_LINE8 DMAMUX_CxCR_SYNC_ID_3 /*!< Synchronization signal from EXTI Line8 */ +#define LL_DMAMUX_SYNC_EXTI_LINE9 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line9 */ +#define LL_DMAMUX_SYNC_EXTI_LINE10 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_1) /*!< Synchronization signal from EXTI Line10 */ +#define LL_DMAMUX_SYNC_EXTI_LINE11 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line11 */ +#define LL_DMAMUX_SYNC_EXTI_LINE12 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_2) /*!< Synchronization signal from EXTI Line12 */ +#define LL_DMAMUX_SYNC_EXTI_LINE13 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line13 */ +#define LL_DMAMUX_SYNC_EXTI_LINE14 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_1) /*!< Synchronization signal from EXTI Line14 */ +#define LL_DMAMUX_SYNC_EXTI_LINE15 (DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from EXTI Line15 */ +#define LL_DMAMUX_SYNC_DMAMUX_CH0 DMAMUX_CxCR_SYNC_ID_4 /*!< Synchronization signal from DMAMUX channel0 Event */ +#define LL_DMAMUX_SYNC_DMAMUX_CH1 (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from DMAMUX channel1 Event */ +#define LL_DMAMUX_SYNC_DMAMUX_CH2 (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_1) /*!< Synchronization signal from DMAMUX channel2 Event */ +#define LL_DMAMUX_SYNC_DMAMUX_CH3 (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from DMAMUX channel3 Event */ +#define LL_DMAMUX_SYNC_LPTIM1_OUT (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_2) /*!< Synchronization signal from LPTIM1 Output */ +#define LL_DMAMUX_SYNC_LPTIM2_OUT (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from LPTIM2 Output */ +#define LL_DMAMUX_SYNC_DSI_TE (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_1) /*!< Synchronization signal from DSI Tearing Effect */ +#define LL_DMAMUX_SYNC_DSI_REFRESH_END (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_2 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from DSI End of Refresh */ +#define LL_DMAMUX_SYNC_DMA2D_TX_END (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_3) /*!< Synchronization signal from DMA2D End of Transfer */ +#define LL_DMAMUX_SYNC_LTDC_LINE_IT (DMAMUX_CxCR_SYNC_ID_4 | DMAMUX_CxCR_SYNC_ID_3 | DMAMUX_CxCR_SYNC_ID_0) /*!< Synchronization signal from LTDC Line Interrupt */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_REQUEST_GENERATOR Request Generator Channel + * @{ + */ +#define LL_DMAMUX_REQ_GEN_0 0x00000000U +#define LL_DMAMUX_REQ_GEN_1 0x00000001U +#define LL_DMAMUX_REQ_GEN_2 0x00000002U +#define LL_DMAMUX_REQ_GEN_3 0x00000003U +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_REQUEST_GEN_POLARITY External Request Signal Generation Polarity + * @{ + */ +#define LL_DMAMUX_REQ_GEN_NO_EVENT 0x00000000U /*!< No external DMA request generation */ +#define LL_DMAMUX_REQ_GEN_POL_RISING DMAMUX_RGxCR_GPOL_0 /*!< External DMA request generation on event on rising edge */ +#define LL_DMAMUX_REQ_GEN_POL_FALLING DMAMUX_RGxCR_GPOL_1 /*!< External DMA request generation on event on falling edge */ +#define LL_DMAMUX_REQ_GEN_POL_RISING_FALLING (DMAMUX_RGxCR_GPOL_0 | DMAMUX_RGxCR_GPOL_1) /*!< External DMA request generation on rising and falling edge */ +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EC_REQUEST_GEN External Request Signal Generation + * @{ + */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE0 0x00000000U /*!< Request signal generation from EXTI Line0 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE1 DMAMUX_RGxCR_SIG_ID_0 /*!< Request signal generation from EXTI Line1 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE2 DMAMUX_RGxCR_SIG_ID_1 /*!< Request signal generation from EXTI Line2 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE3 (DMAMUX_RGxCR_SIG_ID_1 |DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line3 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE4 DMAMUX_RGxCR_SIG_ID_2 /*!< Request signal generation from EXTI Line4 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE5 (DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line5 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE6 (DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_1) /*!< Request signal generation from EXTI Line6 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE7 (DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_1 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line7 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE8 DMAMUX_RGxCR_SIG_ID_3 /*!< Request signal generation from EXTI Line8 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE9 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line9 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE10 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_1) /*!< Request signal generation from EXTI Line10 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE11 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_1 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line11 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE12 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_2) /*!< Request signal generation from EXTI Line12 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE13 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line13 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE14 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_1) /*!< Request signal generation from EXTI Line14 */ +#define LL_DMAMUX_REQ_GEN_EXTI_LINE15 (DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_1 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from EXTI Line15 */ +#define LL_DMAMUX_REQ_GEN_DMAMUX_CH0 DMAMUX_RGxCR_SIG_ID_4 /*!< Request signal generation from DMAMUX channel0 Event */ +#define LL_DMAMUX_REQ_GEN_DMAMUX_CH1 (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from DMAMUX channel1 Event */ +#define LL_DMAMUX_REQ_GEN_DMAMUX_CH2 (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_1) /*!< Request signal generation from DMAMUX channel2 Event */ +#define LL_DMAMUX_REQ_GEN_DMAMUX_CH3 (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_1 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from DMAMUX channel3 Event */ +#define LL_DMAMUX_REQ_GEN_LPTIM1_OUT (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_2) /*!< Request signal generation from LPTIM1 Output */ +#define LL_DMAMUX_REQ_GEN_LPTIM2_OUT (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from LPTIM2 Output */ +#define LL_DMAMUX_REQ_GEN_DSI_TE (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_1) /*!< Request signal generation from DSI Tearing Effect */ +#define LL_DMAMUX_REQ_GEN_DSI_REFRESH_END (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_2 | DMAMUX_RGxCR_SIG_ID_1 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from DSI End of Refresh */ +#define LL_DMAMUX_REQ_GEN_DMA2D_TX_END (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_3) /*!< Request signal generation from DMA2D End of Transfer */ +#define LL_DMAMUX_REQ_GEN_LTDC_LINE_IT (DMAMUX_RGxCR_SIG_ID_4 | DMAMUX_RGxCR_SIG_ID_3 | DMAMUX_RGxCR_SIG_ID_0) /*!< Request signal generation from LTDC Line Interrupt */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup DMAMUX_LL_Exported_Macros DMAMUX Exported Macros + * @{ + */ + +/** @defgroup DMAMUX_LL_EM_WRITE_READ Common Write and read registers macros + * @{ + */ +/** + * @brief Write a value in DMAMUX register + * @param __INSTANCE__ DMAMUX Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_DMAMUX_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in DMAMUX register + * @param __INSTANCE__ DMAMUX Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_DMAMUX_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DMAMUX_LL_Exported_Functions DMAMUX Exported Functions + * @{ + */ + +/** @defgroup DMAMUX_LL_EF_Configuration Configuration + * @{ + */ +/** + * @brief Set DMAMUX request ID for DMAMUX Channel x. + * @note DMAMUX channel 0 to 6 are mapped to DMA1 channel 1 to 7. + * DMAMUX channel 7 to 13 are mapped to DMA2 channel 1 to 7. + * @rmtoll CxCR DMAREQ_ID LL_DMAMUX_SetRequestID + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @param Request This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_MEM2MEM + * @arg @ref LL_DMAMUX_REQ_GENERATOR0 + * @arg @ref LL_DMAMUX_REQ_GENERATOR1 + * @arg @ref LL_DMAMUX_REQ_GENERATOR2 + * @arg @ref LL_DMAMUX_REQ_GENERATOR3 + * @arg @ref LL_DMAMUX_REQ_ADC1 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH1 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM6_UP + * @arg @ref LL_DMAMUX_REQ_TIM7_UP + * @arg @ref LL_DMAMUX_REQ_SPI1_RX + * @arg @ref LL_DMAMUX_REQ_SPI1_TX + * @arg @ref LL_DMAMUX_REQ_SPI2_RX + * @arg @ref LL_DMAMUX_REQ_SPI2_TX + * @arg @ref LL_DMAMUX_REQ_SPI3_RX + * @arg @ref LL_DMAMUX_REQ_SPI3_TX + * @arg @ref LL_DMAMUX_REQ_I2C1_RX + * @arg @ref LL_DMAMUX_REQ_I2C1_TX + * @arg @ref LL_DMAMUX_REQ_I2C2_RX + * @arg @ref LL_DMAMUX_REQ_I2C2_TX + * @arg @ref LL_DMAMUX_REQ_I2C3_RX + * @arg @ref LL_DMAMUX_REQ_I2C3_TX + * @arg @ref LL_DMAMUX_REQ_I2C4_RX + * @arg @ref LL_DMAMUX_REQ_I2C4_TX + * @arg @ref LL_DMAMUX_REQ_USART1_RX + * @arg @ref LL_DMAMUX_REQ_USART1_TX + * @arg @ref LL_DMAMUX_REQ_USART2_RX + * @arg @ref LL_DMAMUX_REQ_USART2_TX + * @arg @ref LL_DMAMUX_REQ_USART3_RX + * @arg @ref LL_DMAMUX_REQ_USART3_TX + * @arg @ref LL_DMAMUX_REQ_UART4_RX + * @arg @ref LL_DMAMUX_REQ_UART4_TX + * @arg @ref LL_DMAMUX_REQ_UART5_RX + * @arg @ref LL_DMAMUX_REQ_UART5_TX + * @arg @ref LL_DMAMUX_REQ_LPUART1_RX + * @arg @ref LL_DMAMUX_REQ_LPUART1_TX + * @arg @ref LL_DMAMUX_REQ_SAI1_A + * @arg @ref LL_DMAMUX_REQ_SAI1_B + * @arg @ref LL_DMAMUX_REQ_SAI2_A + * @arg @ref LL_DMAMUX_REQ_SAI2_B + * @arg @ref LL_DMAMUX_REQ_OSPI1 + * @arg @ref LL_DMAMUX_REQ_OSPI2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM1_UP + * @arg @ref LL_DMAMUX_REQ_TIM1_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM1_COM + * @arg @ref LL_DMAMUX_REQ_TIM8_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM8_UP + * @arg @ref LL_DMAMUX_REQ_TIM8_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM8_COM + * @arg @ref LL_DMAMUX_REQ_TIM2_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM2_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM3_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM4_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM4_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM5_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM15_UP + * @arg @ref LL_DMAMUX_REQ_TIM15_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_COM + * @arg @ref LL_DMAMUX_REQ_TIM16_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM16_UP + * @arg @ref LL_DMAMUX_REQ_TIM17_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM17_UP + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT0 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT1 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT2 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT3 + * @arg @ref LL_DMAMUX_REQ_DCMI + * @arg @ref LL_DMAMUX_REQ_AES_IN + * @arg @ref LL_DMAMUX_REQ_AES_OUT + * @arg @ref LL_DMAMUX_REQ_HASH_IN + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetRequestID(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel, uint32_t Request) +{ + (void)(DMAMUXx); + MODIFY_REG((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_DMAREQ_ID, Request); +} + +/** + * @brief Get DMAMUX request ID for DMAMUX Channel x. + * @note DMAMUX channel 0 to 6 are mapped to DMA1 channel 1 to 7. + * DMAMUX channel 7 to 13 are mapped to DMA2 channel 1 to 7. + * @rmtoll CxCR DMAREQ_ID LL_DMAMUX_GetRequestID + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_MEM2MEM + * @arg @ref LL_DMAMUX_REQ_GENERATOR0 + * @arg @ref LL_DMAMUX_REQ_GENERATOR1 + * @arg @ref LL_DMAMUX_REQ_GENERATOR2 + * @arg @ref LL_DMAMUX_REQ_GENERATOR3 + * @arg @ref LL_DMAMUX_REQ_ADC1 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH1 + * @arg @ref LL_DMAMUX_REQ_DAC1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM6_UP + * @arg @ref LL_DMAMUX_REQ_TIM7_UP + * @arg @ref LL_DMAMUX_REQ_SPI1_RX + * @arg @ref LL_DMAMUX_REQ_SPI1_TX + * @arg @ref LL_DMAMUX_REQ_SPI2_RX + * @arg @ref LL_DMAMUX_REQ_SPI2_TX + * @arg @ref LL_DMAMUX_REQ_SPI3_RX + * @arg @ref LL_DMAMUX_REQ_SPI3_TX + * @arg @ref LL_DMAMUX_REQ_I2C1_RX + * @arg @ref LL_DMAMUX_REQ_I2C1_TX + * @arg @ref LL_DMAMUX_REQ_I2C2_RX + * @arg @ref LL_DMAMUX_REQ_I2C2_TX + * @arg @ref LL_DMAMUX_REQ_I2C3_RX + * @arg @ref LL_DMAMUX_REQ_I2C3_TX + * @arg @ref LL_DMAMUX_REQ_I2C4_RX + * @arg @ref LL_DMAMUX_REQ_I2C4_TX + * @arg @ref LL_DMAMUX_REQ_USART1_RX + * @arg @ref LL_DMAMUX_REQ_USART1_TX + * @arg @ref LL_DMAMUX_REQ_USART2_RX + * @arg @ref LL_DMAMUX_REQ_USART2_TX + * @arg @ref LL_DMAMUX_REQ_USART3_RX + * @arg @ref LL_DMAMUX_REQ_USART3_TX + * @arg @ref LL_DMAMUX_REQ_UART4_RX + * @arg @ref LL_DMAMUX_REQ_UART4_TX + * @arg @ref LL_DMAMUX_REQ_UART5_RX + * @arg @ref LL_DMAMUX_REQ_UART5_TX + * @arg @ref LL_DMAMUX_REQ_LPUART1_RX + * @arg @ref LL_DMAMUX_REQ_LPUART1_TX + * @arg @ref LL_DMAMUX_REQ_SAI1_A + * @arg @ref LL_DMAMUX_REQ_SAI1_B + * @arg @ref LL_DMAMUX_REQ_SAI2_A + * @arg @ref LL_DMAMUX_REQ_SAI2_B + * @arg @ref LL_DMAMUX_REQ_OSPI1 + * @arg @ref LL_DMAMUX_REQ_OSPI2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM1_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM1_UP + * @arg @ref LL_DMAMUX_REQ_TIM1_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM1_COM + * @arg @ref LL_DMAMUX_REQ_TIM8_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM8_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM8_UP + * @arg @ref LL_DMAMUX_REQ_TIM8_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM8_COM + * @arg @ref LL_DMAMUX_REQ_TIM2_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM2_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM2_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM3_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM3_UP + * @arg @ref LL_DMAMUX_REQ_TIM3_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM4_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM4_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM4_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH2 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH3 + * @arg @ref LL_DMAMUX_REQ_TIM5_CH4 + * @arg @ref LL_DMAMUX_REQ_TIM5_UP + * @arg @ref LL_DMAMUX_REQ_TIM5_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM15_UP + * @arg @ref LL_DMAMUX_REQ_TIM15_TRIG + * @arg @ref LL_DMAMUX_REQ_TIM15_COM + * @arg @ref LL_DMAMUX_REQ_TIM16_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM16_UP + * @arg @ref LL_DMAMUX_REQ_TIM17_CH1 + * @arg @ref LL_DMAMUX_REQ_TIM17_UP + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT0 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT1 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT2 + * @arg @ref LL_DMAMUX_REQ_DFSDM1_FLT3 + * @arg @ref LL_DMAMUX_REQ_DCMI + * @arg @ref LL_DMAMUX_REQ_AES_IN + * @arg @ref LL_DMAMUX_REQ_AES_OUT + * @arg @ref LL_DMAMUX_REQ_HASH_IN + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetRequestID(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return (uint32_t)(READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_DMAREQ_ID)); +} + +/** + * @brief Set the number of DMA request that will be autorized after a synchronization event and/or the number of DMA request needed to generate an event. + * @rmtoll CxCR NBREQ LL_DMAMUX_SetSyncRequestNb + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @param RequestNb This parameter must be a value between Min_Data = 1 and Max_Data = 32. + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetSyncRequestNb(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel, uint32_t RequestNb) +{ + (void)(DMAMUXx); + MODIFY_REG((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_NBREQ, ((RequestNb - 1U) << DMAMUX_CxCR_NBREQ_Pos)); +} + +/** + * @brief Get the number of DMA request that will be autorized after a synchronization event and/or the number of DMA request needed to generate an event. + * @rmtoll CxCR NBREQ LL_DMAMUX_GetSyncRequestNb + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval Between Min_Data = 1 and Max_Data = 32 + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetSyncRequestNb(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return (uint32_t)(((READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_NBREQ)) >> DMAMUX_CxCR_NBREQ_Pos) + 1U); +} + +/** + * @brief Set the polarity of the signal on which the DMA request is synchronized. + * @rmtoll CxCR SPOL LL_DMAMUX_SetSyncPolarity + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_SYNC_NO_EVENT + * @arg @ref LL_DMAMUX_SYNC_POL_RISING + * @arg @ref LL_DMAMUX_SYNC_POL_FALLING + * @arg @ref LL_DMAMUX_SYNC_POL_RISING_FALLING + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetSyncPolarity(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel, uint32_t Polarity) +{ + (void)(DMAMUXx); + MODIFY_REG((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SPOL, Polarity); +} + +/** + * @brief Get the polarity of the signal on which the DMA request is synchronized. + * @rmtoll CxCR SPOL LL_DMAMUX_GetSyncPolarity + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMAMUX_SYNC_NO_EVENT + * @arg @ref LL_DMAMUX_SYNC_POL_RISING + * @arg @ref LL_DMAMUX_SYNC_POL_FALLING + * @arg @ref LL_DMAMUX_SYNC_POL_RISING_FALLING + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetSyncPolarity(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return (uint32_t)(READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SPOL)); +} + +/** + * @brief Enable the Event Generation on DMAMUX channel x. + * @rmtoll CxCR EGE LL_DMAMUX_EnableEventGeneration + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_EnableEventGeneration(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + SET_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_EGE); +} + +/** + * @brief Disable the Event Generation on DMAMUX channel x. + * @rmtoll CxCR EGE LL_DMAMUX_DisableEventGeneration + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_DisableEventGeneration(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + CLEAR_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_EGE); +} + +/** + * @brief Check if the Event Generation on DMAMUX channel x is enabled or disabled. + * @rmtoll CxCR EGE LL_DMAMUX_IsEnabledEventGeneration + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsEnabledEventGeneration(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return ((READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_EGE) == (DMAMUX_CxCR_EGE)) ? 1UL : 0UL); +} + +/** + * @brief Enable the synchronization mode. + * @rmtoll CxCR SE LL_DMAMUX_EnableSync + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_EnableSync(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + SET_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SE); +} + +/** + * @brief Disable the synchronization mode. + * @rmtoll CxCR SE LL_DMAMUX_DisableSync + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_DisableSync(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + CLEAR_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SE); +} + +/** + * @brief Check if the synchronization mode is enabled or disabled. + * @rmtoll CxCR SE LL_DMAMUX_IsEnabledSync + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsEnabledSync(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return ((READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SE) == (DMAMUX_CxCR_SE)) ? 1UL : 0UL); +} + +/** + * @brief Set DMAMUX synchronization ID on DMAMUX Channel x. + * @rmtoll CxCR SYNC_ID LL_DMAMUX_SetSyncID + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @param SyncID This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE0 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE1 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE2 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE3 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE4 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE5 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE6 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE7 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE8 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE9 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE10 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE11 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE12 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE13 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE14 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE15 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH0 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH1 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH2 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH3 + * @arg @ref LL_DMAMUX_SYNC_LPTIM1_OUT + * @arg @ref LL_DMAMUX_SYNC_LPTIM2_OUT + * @arg @ref LL_DMAMUX_SYNC_DSI_TE + * @arg @ref LL_DMAMUX_SYNC_DSI_REFRESH_END + * @arg @ref LL_DMAMUX_SYNC_DMA2D_TX_END + * @arg @ref LL_DMAMUX_SYNC_LTDC_LINE_IT + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetSyncID(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel, uint32_t SyncID) +{ + (void)(DMAMUXx); + MODIFY_REG((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SYNC_ID, SyncID); +} + +/** + * @brief Get DMAMUX synchronization ID on DMAMUX Channel x. + * @rmtoll CxCR SYNC_ID LL_DMAMUX_GetSyncID + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE0 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE1 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE2 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE3 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE4 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE5 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE6 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE7 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE8 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE9 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE10 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE11 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE12 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE13 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE14 + * @arg @ref LL_DMAMUX_SYNC_EXTI_LINE15 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH0 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH1 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH2 + * @arg @ref LL_DMAMUX_SYNC_DMAMUX_CH3 + * @arg @ref LL_DMAMUX_SYNC_LPTIM1_OUT + * @arg @ref LL_DMAMUX_SYNC_LPTIM2_OUT + * @arg @ref LL_DMAMUX_SYNC_DSI_TE + * @arg @ref LL_DMAMUX_SYNC_DSI_REFRESH_END + * @arg @ref LL_DMAMUX_SYNC_DMA2D_TX_END + * @arg @ref LL_DMAMUX_SYNC_LTDC_LINE_IT + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetSyncID(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return (uint32_t)(READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SYNC_ID)); +} + +/** + * @brief Enable the Request Generator. + * @rmtoll RGxCR GE LL_DMAMUX_EnableRequestGen + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_EnableRequestGen(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + SET_BIT(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GE); +} + +/** + * @brief Disable the Request Generator. + * @rmtoll RGxCR GE LL_DMAMUX_DisableRequestGen + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_DisableRequestGen(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + CLEAR_BIT(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GE); +} + +/** + * @brief Check if the Request Generator is enabled or disabled. + * @rmtoll RGxCR GE LL_DMAMUX_IsEnabledRequestGen + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsEnabledRequestGen(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + return ((READ_BIT(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GE) == (DMAMUX_RGxCR_GE)) ? 1UL : 0UL); +} + +/** + * @brief Set the polarity of the signal on which the DMA request is generated. + * @rmtoll RGxCR GPOL LL_DMAMUX_SetRequestGenPolarity + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_NO_EVENT + * @arg @ref LL_DMAMUX_REQ_GEN_POL_RISING + * @arg @ref LL_DMAMUX_REQ_GEN_POL_FALLING + * @arg @ref LL_DMAMUX_REQ_GEN_POL_RISING_FALLING + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetRequestGenPolarity(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel, uint32_t Polarity) +{ + (void)(DMAMUXx); + MODIFY_REG(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GPOL, Polarity); +} + +/** + * @brief Get the polarity of the signal on which the DMA request is generated. + * @rmtoll RGxCR GPOL LL_DMAMUX_GetRequestGenPolarity + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_NO_EVENT + * @arg @ref LL_DMAMUX_REQ_GEN_POL_RISING + * @arg @ref LL_DMAMUX_REQ_GEN_POL_FALLING + * @arg @ref LL_DMAMUX_REQ_GEN_POL_RISING_FALLING + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetRequestGenPolarity(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + return (uint32_t)(READ_BIT(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GPOL)); +} + +/** + * @brief Set the number of DMA request that will be autorized after a generation event. + * @note This field can only be written when Generator is disabled. + * @rmtoll RGxCR GNBREQ LL_DMAMUX_SetGenRequestNb + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @param RequestNb This parameter must be a value between Min_Data = 1 and Max_Data = 32. + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetGenRequestNb(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel, uint32_t RequestNb) +{ + (void)(DMAMUXx); + MODIFY_REG(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GNBREQ, (RequestNb - 1U) << DMAMUX_RGxCR_GNBREQ_Pos); +} + +/** + * @brief Get the number of DMA request that will be autorized after a generation event. + * @rmtoll RGxCR GNBREQ LL_DMAMUX_GetGenRequestNb + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval Between Min_Data = 1 and Max_Data = 32 + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetGenRequestNb(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + return (uint32_t)((READ_BIT(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_GNBREQ) >> DMAMUX_RGxCR_GNBREQ_Pos) + 1U); +} + +/** + * @brief Set DMAMUX external Request Signal ID on DMAMUX Request Generation Trigger Event Channel x. + * @rmtoll RGxCR SIG_ID LL_DMAMUX_SetRequestSignalID + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @param RequestSignalID This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE0 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE1 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE2 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE3 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE4 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE5 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE6 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE7 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE8 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE9 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE10 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE11 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE12 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE13 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE14 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE15 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH0 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH1 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH2 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH3 + * @arg @ref LL_DMAMUX_REQ_GEN_LPTIM1_OUT + * @arg @ref LL_DMAMUX_REQ_GEN_LPTIM2_OUT + * @arg @ref LL_DMAMUX_REQ_GEN_DSI_TE + * @arg @ref LL_DMAMUX_REQ_GEN_DSI_REFRESH_END + * @arg @ref LL_DMAMUX_REQ_GEN_DMA2D_TX_END + * @arg @ref LL_DMAMUX_REQ_GEN_LTDC_LINE_IT + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_SetRequestSignalID(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel, uint32_t RequestSignalID) +{ + (void)(DMAMUXx); + MODIFY_REG(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_SIG_ID, RequestSignalID); +} + +/** + * @brief Get DMAMUX external Request Signal ID set on DMAMUX Channel x. + * @rmtoll RGxCR SIG_ID LL_DMAMUX_GetRequestSignalID + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE0 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE1 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE2 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE3 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE4 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE5 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE6 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE7 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE8 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE9 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE10 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE11 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE12 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE13 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE14 + * @arg @ref LL_DMAMUX_REQ_GEN_EXTI_LINE15 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH0 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH1 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH2 + * @arg @ref LL_DMAMUX_REQ_GEN_DMAMUX_CH3 + * @arg @ref LL_DMAMUX_REQ_GEN_LPTIM1_OUT + * @arg @ref LL_DMAMUX_REQ_GEN_LPTIM2_OUT + * @arg @ref LL_DMAMUX_REQ_GEN_DSI_TE + * @arg @ref LL_DMAMUX_REQ_GEN_DSI_REFRESH_END + * @arg @ref LL_DMAMUX_REQ_GEN_DMA2D_TX_END + * @arg @ref LL_DMAMUX_REQ_GEN_LTDC_LINE_IT + */ +__STATIC_INLINE uint32_t LL_DMAMUX_GetRequestSignalID(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + return (uint32_t)(READ_BIT(((DMAMUX_RequestGen_TypeDef *)((uint32_t)((uint32_t)DMAMUX1_RequestGenerator0 + (DMAMUX_RGCR_SIZE * (RequestGenChannel)))))->RGCR, DMAMUX_RGxCR_SIG_ID)); +} + +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Get Synchronization Event Overrun Flag Channel 0. + * @rmtoll CSR SOF0 LL_DMAMUX_IsActiveFlag_SO0 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO0(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF0) == (DMAMUX_CSR_SOF0)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 1. + * @rmtoll CSR SOF1 LL_DMAMUX_IsActiveFlag_SO1 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO1(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF1) == (DMAMUX_CSR_SOF1)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 2. + * @rmtoll CSR SOF2 LL_DMAMUX_IsActiveFlag_SO2 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO2(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF2) == (DMAMUX_CSR_SOF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 3. + * @rmtoll CSR SOF3 LL_DMAMUX_IsActiveFlag_SO3 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO3(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF3) == (DMAMUX_CSR_SOF3)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 4. + * @rmtoll CSR SOF4 LL_DMAMUX_IsActiveFlag_SO4 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO4(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF4) == (DMAMUX_CSR_SOF4)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 5. + * @rmtoll CSR SOF5 LL_DMAMUX_IsActiveFlag_SO5 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO5(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF5) == (DMAMUX_CSR_SOF5)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 6. + * @rmtoll CSR SOF6 LL_DMAMUX_IsActiveFlag_SO6 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO6(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF6) == (DMAMUX_CSR_SOF6)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 7. + * @rmtoll CSR SOF7 LL_DMAMUX_IsActiveFlag_SO7 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO7(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF7) == (DMAMUX_CSR_SOF7)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 8. + * @rmtoll CSR SOF8 LL_DMAMUX_IsActiveFlag_SO8 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO8(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF8) == (DMAMUX_CSR_SOF8)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 9. + * @rmtoll CSR SOF9 LL_DMAMUX_IsActiveFlag_SO9 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO9(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF9) == (DMAMUX_CSR_SOF9)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 10. + * @rmtoll CSR SOF10 LL_DMAMUX_IsActiveFlag_SO10 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO10(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF10) == (DMAMUX_CSR_SOF10)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 11. + * @rmtoll CSR SOF11 LL_DMAMUX_IsActiveFlag_SO11 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO11(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF11) == (DMAMUX_CSR_SOF11)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 12. + * @rmtoll CSR SOF12 LL_DMAMUX_IsActiveFlag_SO12 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO12(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF12) == (DMAMUX_CSR_SOF12)) ? 1UL : 0UL); +} + +/** + * @brief Get Synchronization Event Overrun Flag Channel 13. + * @rmtoll CSR SOF13 LL_DMAMUX_IsActiveFlag_SO13 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_SO13(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_ChannelStatus->CSR, DMAMUX_CSR_SOF13) == (DMAMUX_CSR_SOF13)) ? 1UL : 0UL); +} + +/** + * @brief Get Request Generator 0 Trigger Event Overrun Flag. + * @rmtoll RGSR OF0 LL_DMAMUX_IsActiveFlag_RGO0 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_RGO0(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_RequestGenStatus->RGSR, DMAMUX_RGSR_OF0) == (DMAMUX_RGSR_OF0)) ? 1UL : 0UL); +} + +/** + * @brief Get Request Generator 1 Trigger Event Overrun Flag. + * @rmtoll RGSR OF1 LL_DMAMUX_IsActiveFlag_RGO1 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_RGO1(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_RequestGenStatus->RGSR, DMAMUX_RGSR_OF1) == (DMAMUX_RGSR_OF1)) ? 1UL : 0UL); +} + +/** + * @brief Get Request Generator 2 Trigger Event Overrun Flag. + * @rmtoll RGSR OF2 LL_DMAMUX_IsActiveFlag_RGO2 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_RGO2(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_RequestGenStatus->RGSR, DMAMUX_RGSR_OF2) == (DMAMUX_RGSR_OF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Request Generator 3 Trigger Event Overrun Flag. + * @rmtoll RGSR OF3 LL_DMAMUX_IsActiveFlag_RGO3 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsActiveFlag_RGO3(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + return ((READ_BIT(DMAMUX1_RequestGenStatus->RGSR, DMAMUX_RGSR_OF3) == (DMAMUX_RGSR_OF3)) ? 1UL : 0UL); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 0. + * @rmtoll CFR CSOF0 LL_DMAMUX_ClearFlag_SO0 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO0(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF0); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 1. + * @rmtoll CFR CSOF1 LL_DMAMUX_ClearFlag_SO1 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO1(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF1); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 2. + * @rmtoll CFR CSOF2 LL_DMAMUX_ClearFlag_SO2 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO2(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF2); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 3. + * @rmtoll CFR CSOF3 LL_DMAMUX_ClearFlag_SO3 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO3(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF3); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 4. + * @rmtoll CFR CSOF4 LL_DMAMUX_ClearFlag_SO4 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO4(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF4); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 5. + * @rmtoll CFR CSOF5 LL_DMAMUX_ClearFlag_SO5 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO5(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF5); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 6. + * @rmtoll CFR CSOF6 LL_DMAMUX_ClearFlag_SO6 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO6(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF6); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 7. + * @rmtoll CFR CSOF7 LL_DMAMUX_ClearFlag_SO7 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO7(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF7); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 8. + * @rmtoll CFR CSOF8 LL_DMAMUX_ClearFlag_SO8 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO8(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF8); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 9. + * @rmtoll CFR CSOF9 LL_DMAMUX_ClearFlag_SO9 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO9(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF9); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 10. + * @rmtoll CFR CSOF10 LL_DMAMUX_ClearFlag_SO10 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO10(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF10); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 11. + * @rmtoll CFR CSOF11 LL_DMAMUX_ClearFlag_SO11 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO11(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF11); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 12. + * @rmtoll CFR CSOF12 LL_DMAMUX_ClearFlag_SO12 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO12(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF12); +} + +/** + * @brief Clear Synchronization Event Overrun Flag Channel 13. + * @rmtoll CFR CSOF13 LL_DMAMUX_ClearFlag_SO13 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_SO13(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_ChannelStatus->CFR, DMAMUX_CFR_CSOF13); +} + +/** + * @brief Clear Request Generator 0 Trigger Event Overrun Flag. + * @rmtoll RGCFR COF0 LL_DMAMUX_ClearFlag_RGO0 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_RGO0(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_RequestGenStatus->RGCFR, DMAMUX_RGCFR_COF0); +} + +/** + * @brief Clear Request Generator 1 Trigger Event Overrun Flag. + * @rmtoll RGCFR COF1 LL_DMAMUX_ClearFlag_RGO1 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_RGO1(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_RequestGenStatus->RGCFR, DMAMUX_RGCFR_COF1); +} + +/** + * @brief Clear Request Generator 2 Trigger Event Overrun Flag. + * @rmtoll RGCFR COF2 LL_DMAMUX_ClearFlag_RGO2 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_RGO2(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_RequestGenStatus->RGCFR, DMAMUX_RGCFR_COF2); +} + +/** + * @brief Clear Request Generator 3 Trigger Event Overrun Flag. + * @rmtoll RGCFR COF3 LL_DMAMUX_ClearFlag_RGO3 + * @param DMAMUXx DMAMUXx DMAMUXx Instance + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_ClearFlag_RGO3(DMAMUX_Channel_TypeDef *DMAMUXx) +{ + (void)(DMAMUXx); + SET_BIT(DMAMUX1_RequestGenStatus->RGCFR, DMAMUX_RGCFR_COF3); +} + +/** + * @} + */ + +/** @defgroup DMAMUX_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable the Synchronization Event Overrun Interrupt on DMAMUX channel x. + * @rmtoll CxCR SOIE LL_DMAMUX_EnableIT_SO + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_EnableIT_SO(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + SET_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SOIE); +} + +/** + * @brief Disable the Synchronization Event Overrun Interrupt on DMAMUX channel x. + * @rmtoll CxCR SOIE LL_DMAMUX_DisableIT_SO + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_DisableIT_SO(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + CLEAR_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SOIE); +} + +/** + * @brief Check if the Synchronization Event Overrun Interrupt on DMAMUX channel x is enabled or disabled. + * @rmtoll CxCR SOIE LL_DMAMUX_IsEnabledIT_SO + * @param DMAMUXx DMAMUXx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_CHANNEL_0 + * @arg @ref LL_DMAMUX_CHANNEL_1 + * @arg @ref LL_DMAMUX_CHANNEL_2 + * @arg @ref LL_DMAMUX_CHANNEL_3 + * @arg @ref LL_DMAMUX_CHANNEL_4 + * @arg @ref LL_DMAMUX_CHANNEL_5 + * @arg @ref LL_DMAMUX_CHANNEL_6 + * @arg @ref LL_DMAMUX_CHANNEL_7 + * @arg @ref LL_DMAMUX_CHANNEL_8 + * @arg @ref LL_DMAMUX_CHANNEL_9 + * @arg @ref LL_DMAMUX_CHANNEL_10 + * @arg @ref LL_DMAMUX_CHANNEL_11 + * @arg @ref LL_DMAMUX_CHANNEL_12 + * @arg @ref LL_DMAMUX_CHANNEL_13 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsEnabledIT_SO(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t Channel) +{ + (void)(DMAMUXx); + return (((READ_BIT((DMAMUX1_Channel0 + Channel)->CCR, DMAMUX_CxCR_SOIE)) == (DMAMUX_CxCR_SOIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable the Request Generation Trigger Event Overrun Interrupt on DMAMUX channel x. + * @rmtoll RGxCR OIE LL_DMAMUX_EnableIT_RGO + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_EnableIT_RGO(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + SET_BIT((DMAMUX1_RequestGenerator0 + RequestGenChannel)->RGCR, DMAMUX_RGxCR_OIE); +} + +/** + * @brief Disable the Request Generation Trigger Event Overrun Interrupt on DMAMUX channel x. + * @rmtoll RGxCR OIE LL_DMAMUX_DisableIT_RGO + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval None + */ +__STATIC_INLINE void LL_DMAMUX_DisableIT_RGO(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + CLEAR_BIT((DMAMUX1_RequestGenerator0 + RequestGenChannel)->RGCR, DMAMUX_RGxCR_OIE); +} + +/** + * @brief Check if the Request Generation Trigger Event Overrun Interrupt on DMAMUX channel x is enabled or disabled. + * @rmtoll RGxCR OIE LL_DMAMUX_IsEnabledIT_RGO + * @param DMAMUXx DMAMUXx Instance + * @param RequestGenChannel This parameter can be one of the following values: + * @arg @ref LL_DMAMUX_REQ_GEN_0 + * @arg @ref LL_DMAMUX_REQ_GEN_1 + * @arg @ref LL_DMAMUX_REQ_GEN_2 + * @arg @ref LL_DMAMUX_REQ_GEN_3 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMAMUX_IsEnabledIT_RGO(DMAMUX_Channel_TypeDef *DMAMUXx, uint32_t RequestGenChannel) +{ + (void)(DMAMUXx); + return ((READ_BIT((DMAMUX1_RequestGenerator0 + RequestGenChannel)->RGCR, DMAMUX_RGxCR_OIE) == (DMAMUX_RGxCR_OIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMAMUX1 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_DMAMUX_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_exti.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_exti.h new file mode 100644 index 0000000..a1ee112 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_exti.h @@ -0,0 +1,1359 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_exti.h + * @author MCD Application Team + * @brief Header file of EXTI 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 STM32L4xx_LL_EXTI_H +#define STM32L4xx_LL_EXTI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (EXTI) + +/** @defgroup EXTI_LL EXTI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private Macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup EXTI_LL_Private_Macros EXTI Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup EXTI_LL_ES_INIT EXTI Exported Init structure + * @{ + */ +typedef struct +{ + + uint32_t Line_0_31; /*!< Specifies the EXTI lines to be enabled or disabled for Lines in range 0 to 31 + This parameter can be any combination of @ref EXTI_LL_EC_LINE */ + + uint32_t Line_32_63; /*!< Specifies the EXTI lines to be enabled or disabled for Lines in range 32 to 63 + This parameter can be any combination of @ref EXTI_LL_EC_LINE */ + + FunctionalState LineCommand; /*!< Specifies the new state of the selected EXTI lines. + This parameter can be set either to ENABLE or DISABLE */ + + uint8_t Mode; /*!< Specifies the mode for the EXTI lines. + This parameter can be a value of @ref EXTI_LL_EC_MODE. */ + + uint8_t Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. + This parameter can be a value of @ref EXTI_LL_EC_TRIGGER. */ +} LL_EXTI_InitTypeDef; + +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup EXTI_LL_Exported_Constants EXTI Exported Constants + * @{ + */ + +/** @defgroup EXTI_LL_EC_LINE LINE + * @{ + */ +#define LL_EXTI_LINE_0 EXTI_IMR1_IM0 /*!< Extended line 0 */ +#define LL_EXTI_LINE_1 EXTI_IMR1_IM1 /*!< Extended line 1 */ +#define LL_EXTI_LINE_2 EXTI_IMR1_IM2 /*!< Extended line 2 */ +#define LL_EXTI_LINE_3 EXTI_IMR1_IM3 /*!< Extended line 3 */ +#define LL_EXTI_LINE_4 EXTI_IMR1_IM4 /*!< Extended line 4 */ +#define LL_EXTI_LINE_5 EXTI_IMR1_IM5 /*!< Extended line 5 */ +#define LL_EXTI_LINE_6 EXTI_IMR1_IM6 /*!< Extended line 6 */ +#define LL_EXTI_LINE_7 EXTI_IMR1_IM7 /*!< Extended line 7 */ +#define LL_EXTI_LINE_8 EXTI_IMR1_IM8 /*!< Extended line 8 */ +#define LL_EXTI_LINE_9 EXTI_IMR1_IM9 /*!< Extended line 9 */ +#define LL_EXTI_LINE_10 EXTI_IMR1_IM10 /*!< Extended line 10 */ +#define LL_EXTI_LINE_11 EXTI_IMR1_IM11 /*!< Extended line 11 */ +#define LL_EXTI_LINE_12 EXTI_IMR1_IM12 /*!< Extended line 12 */ +#define LL_EXTI_LINE_13 EXTI_IMR1_IM13 /*!< Extended line 13 */ +#define LL_EXTI_LINE_14 EXTI_IMR1_IM14 /*!< Extended line 14 */ +#define LL_EXTI_LINE_15 EXTI_IMR1_IM15 /*!< Extended line 15 */ +#if defined(EXTI_IMR1_IM16) +#define LL_EXTI_LINE_16 EXTI_IMR1_IM16 /*!< Extended line 16 */ +#endif +#define LL_EXTI_LINE_17 EXTI_IMR1_IM17 /*!< Extended line 17 */ +#if defined(EXTI_IMR1_IM18) +#define LL_EXTI_LINE_18 EXTI_IMR1_IM18 /*!< Extended line 18 */ +#endif +#define LL_EXTI_LINE_19 EXTI_IMR1_IM19 /*!< Extended line 19 */ +#if defined(EXTI_IMR1_IM20) +#define LL_EXTI_LINE_20 EXTI_IMR1_IM20 /*!< Extended line 20 */ +#endif +#if defined(EXTI_IMR1_IM21) +#define LL_EXTI_LINE_21 EXTI_IMR1_IM21 /*!< Extended line 21 */ +#endif +#if defined(EXTI_IMR1_IM22) +#define LL_EXTI_LINE_22 EXTI_IMR1_IM22 /*!< Extended line 22 */ +#endif +#define LL_EXTI_LINE_23 EXTI_IMR1_IM23 /*!< Extended line 23 */ +#if defined(EXTI_IMR1_IM24) +#define LL_EXTI_LINE_24 EXTI_IMR1_IM24 /*!< Extended line 24 */ +#endif +#if defined(EXTI_IMR1_IM25) +#define LL_EXTI_LINE_25 EXTI_IMR1_IM25 /*!< Extended line 25 */ +#endif +#if defined(EXTI_IMR1_IM26) +#define LL_EXTI_LINE_26 EXTI_IMR1_IM26 /*!< Extended line 26 */ +#endif +#if defined(EXTI_IMR1_IM27) +#define LL_EXTI_LINE_27 EXTI_IMR1_IM27 /*!< Extended line 27 */ +#endif +#if defined(EXTI_IMR1_IM28) +#define LL_EXTI_LINE_28 EXTI_IMR1_IM28 /*!< Extended line 28 */ +#endif +#if defined(EXTI_IMR1_IM29) +#define LL_EXTI_LINE_29 EXTI_IMR1_IM29 /*!< Extended line 29 */ +#endif +#if defined(EXTI_IMR1_IM30) +#define LL_EXTI_LINE_30 EXTI_IMR1_IM30 /*!< Extended line 30 */ +#endif +#if defined(EXTI_IMR1_IM31) +#define LL_EXTI_LINE_31 EXTI_IMR1_IM31 /*!< Extended line 31 */ +#endif +#define LL_EXTI_LINE_ALL_0_31 EXTI_IMR1_IM /*!< All Extended line not reserved*/ + +#define LL_EXTI_LINE_32 EXTI_IMR2_IM32 /*!< Extended line 32 */ +#if defined(EXTI_IMR2_IM33) +#define LL_EXTI_LINE_33 EXTI_IMR2_IM33 /*!< Extended line 33 */ +#endif +#if defined(EXTI_IMR2_IM34) +#define LL_EXTI_LINE_34 EXTI_IMR2_IM34 /*!< Extended line 34 */ +#endif +#if defined(EXTI_IMR2_IM35) +#define LL_EXTI_LINE_35 EXTI_IMR2_IM35 /*!< Extended line 35 */ +#endif +#if defined(EXTI_IMR2_IM36) +#define LL_EXTI_LINE_36 EXTI_IMR2_IM36 /*!< Extended line 36 */ +#endif +#if defined(EXTI_IMR2_IM37) +#define LL_EXTI_LINE_37 EXTI_IMR2_IM37 /*!< Extended line 37 */ +#endif +#if defined(EXTI_IMR2_IM38) +#define LL_EXTI_LINE_38 EXTI_IMR2_IM38 /*!< Extended line 38 */ +#endif +#if defined(EXTI_IMR2_IM39) +#define LL_EXTI_LINE_39 EXTI_IMR2_IM39 /*!< Extended line 39 */ +#endif +#if defined(EXTI_IMR2_IM40) +#define LL_EXTI_LINE_40 EXTI_IMR2_IM40 /*!< Extended line 40 */ +#endif +#define LL_EXTI_LINE_ALL_32_63 EXTI_IMR2_IM /*!< All Extended line not reserved*/ + + +#define LL_EXTI_LINE_ALL (0xFFFFFFFFU) /*!< All Extended line */ + +#if defined(USE_FULL_LL_DRIVER) +#define LL_EXTI_LINE_NONE (0x00000000U) /*!< None Extended line */ +#endif /*USE_FULL_LL_DRIVER*/ + +/** + * @} + */ + + +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup EXTI_LL_EC_MODE Mode + * @{ + */ +#define LL_EXTI_MODE_IT ((uint8_t)0x00U) /*!< Interrupt Mode */ +#define LL_EXTI_MODE_EVENT ((uint8_t)0x01U) /*!< Event Mode */ +#define LL_EXTI_MODE_IT_EVENT ((uint8_t)0x02U) /*!< Interrupt & Event Mode */ +/** + * @} + */ + +/** @defgroup EXTI_LL_EC_TRIGGER Edge Trigger + * @{ + */ +#define LL_EXTI_TRIGGER_NONE ((uint8_t)0x00U) /*!< No Trigger Mode */ +#define LL_EXTI_TRIGGER_RISING ((uint8_t)0x01U) /*!< Trigger Rising Mode */ +#define LL_EXTI_TRIGGER_FALLING ((uint8_t)0x02U) /*!< Trigger Falling Mode */ +#define LL_EXTI_TRIGGER_RISING_FALLING ((uint8_t)0x03U) /*!< Trigger Rising & Falling Mode */ + +/** + * @} + */ + + +#endif /*USE_FULL_LL_DRIVER*/ + + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup EXTI_LL_Exported_Macros EXTI Exported Macros + * @{ + */ + +/** @defgroup EXTI_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in EXTI register + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_EXTI_WriteReg(__REG__, __VALUE__) WRITE_REG(EXTI->__REG__, (__VALUE__)) + +/** + * @brief Read a value in EXTI register + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_EXTI_ReadReg(__REG__) READ_REG(EXTI->__REG__) +/** + * @} + */ + + +/** + * @} + */ + + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup EXTI_LL_Exported_Functions EXTI Exported Functions + * @{ + */ +/** @defgroup EXTI_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable ExtiLine Interrupt request for Lines in range 0 to 31 + * @note The reset value for the direct or internal lines (see RM) + * is set to 1 in order to enable the interrupt by default. + * Bits are set automatically at Power on. + * @rmtoll IMR1 IMx LL_EXTI_EnableIT_0_31 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_17 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_23 + * @arg @ref LL_EXTI_LINE_24 + * @arg @ref LL_EXTI_LINE_25 + * @arg @ref LL_EXTI_LINE_26 + * @arg @ref LL_EXTI_LINE_27 + * @arg @ref LL_EXTI_LINE_28 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @arg @ref LL_EXTI_LINE_ALL_0_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableIT_0_31(uint32_t ExtiLine) +{ + SET_BIT(EXTI->IMR1, ExtiLine); +} +/** + * @brief Enable ExtiLine Interrupt request for Lines in range 32 to 63 + * @note The reset value for the direct lines (lines from 32 to 34, line + * 39) is set to 1 in order to enable the interrupt by default. + * Bits are set automatically at Power on. + * @rmtoll IMR2 IMx LL_EXTI_EnableIT_32_63 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_32 + * @arg @ref LL_EXTI_LINE_33 + * @arg @ref LL_EXTI_LINE_34(*) + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @arg @ref LL_EXTI_LINE_39(*) + * @arg @ref LL_EXTI_LINE_40(*) + * @arg @ref LL_EXTI_LINE_ALL_32_63 + * @note (*): Available in some devices + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableIT_32_63(uint32_t ExtiLine) +{ + SET_BIT(EXTI->IMR2, ExtiLine); +} + +/** + * @brief Disable ExtiLine Interrupt request for Lines in range 0 to 31 + * @note The reset value for the direct or internal lines (see RM) + * is set to 1 in order to enable the interrupt by default. + * Bits are set automatically at Power on. + * @rmtoll IMR1 IMx LL_EXTI_DisableIT_0_31 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_17 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_23 + * @arg @ref LL_EXTI_LINE_24 + * @arg @ref LL_EXTI_LINE_25 + * @arg @ref LL_EXTI_LINE_26 + * @arg @ref LL_EXTI_LINE_27 + * @arg @ref LL_EXTI_LINE_28 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @arg @ref LL_EXTI_LINE_ALL_0_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableIT_0_31(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->IMR1, ExtiLine); +} + +/** + * @brief Disable ExtiLine Interrupt request for Lines in range 32 to 63 + * @note The reset value for the direct lines (lines from 32 to 34, line + * 39) is set to 1 in order to enable the interrupt by default. + * Bits are set automatically at Power on. + * @rmtoll IMR2 IMx LL_EXTI_DisableIT_32_63 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_32 + * @arg @ref LL_EXTI_LINE_33 + * @arg @ref LL_EXTI_LINE_34(*) + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @arg @ref LL_EXTI_LINE_39(*) + * @arg @ref LL_EXTI_LINE_40(*) + * @arg @ref LL_EXTI_LINE_ALL_32_63 + * @note (*): Available in some devices + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableIT_32_63(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->IMR2, ExtiLine); +} + +/** + * @brief Indicate if ExtiLine Interrupt request is enabled for Lines in range 0 to 31 + * @note The reset value for the direct or internal lines (see RM) + * is set to 1 in order to enable the interrupt by default. + * Bits are set automatically at Power on. + * @rmtoll IMR1 IMx LL_EXTI_IsEnabledIT_0_31 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_17 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_23 + * @arg @ref LL_EXTI_LINE_24 + * @arg @ref LL_EXTI_LINE_25 + * @arg @ref LL_EXTI_LINE_26 + * @arg @ref LL_EXTI_LINE_27 + * @arg @ref LL_EXTI_LINE_28 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @arg @ref LL_EXTI_LINE_ALL_0_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledIT_0_31(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->IMR1, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @brief Indicate if ExtiLine Interrupt request is enabled for Lines in range 32 to 63 + * @note The reset value for the direct lines (lines from 32 to 34, line + * 39) is set to 1 in order to enable the interrupt by default. + * Bits are set automatically at Power on. + * @rmtoll IMR2 IMx LL_EXTI_IsEnabledIT_32_63 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_32 + * @arg @ref LL_EXTI_LINE_33 + * @arg @ref LL_EXTI_LINE_34(*) + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @arg @ref LL_EXTI_LINE_39(*) + * @arg @ref LL_EXTI_LINE_40(*) + * @arg @ref LL_EXTI_LINE_ALL_32_63 + * @note (*): Available in some devices + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledIT_32_63(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->IMR2, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup EXTI_LL_EF_Event_Management Event_Management + * @{ + */ + +/** + * @brief Enable ExtiLine Event request for Lines in range 0 to 31 + * @rmtoll EMR1 EMx LL_EXTI_EnableEvent_0_31 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_17 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_23 + * @arg @ref LL_EXTI_LINE_24 + * @arg @ref LL_EXTI_LINE_25 + * @arg @ref LL_EXTI_LINE_26 + * @arg @ref LL_EXTI_LINE_27 + * @arg @ref LL_EXTI_LINE_28 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @arg @ref LL_EXTI_LINE_ALL_0_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableEvent_0_31(uint32_t ExtiLine) +{ + SET_BIT(EXTI->EMR1, ExtiLine); + +} + +/** + * @brief Enable ExtiLine Event request for Lines in range 32 to 63 + * @rmtoll EMR2 EMx LL_EXTI_EnableEvent_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_32 + * @arg @ref LL_EXTI_LINE_33 + * @arg @ref LL_EXTI_LINE_34(*) + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @arg @ref LL_EXTI_LINE_39(*) + * @arg @ref LL_EXTI_LINE_40(*) + * @arg @ref LL_EXTI_LINE_ALL_32_63 + * @note (*): Available in some devices + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableEvent_32_63(uint32_t ExtiLine) +{ + SET_BIT(EXTI->EMR2, ExtiLine); +} + +/** + * @brief Disable ExtiLine Event request for Lines in range 0 to 31 + * @rmtoll EMR1 EMx LL_EXTI_DisableEvent_0_31 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_17 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_23 + * @arg @ref LL_EXTI_LINE_24 + * @arg @ref LL_EXTI_LINE_25 + * @arg @ref LL_EXTI_LINE_26 + * @arg @ref LL_EXTI_LINE_27 + * @arg @ref LL_EXTI_LINE_28 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @arg @ref LL_EXTI_LINE_ALL_0_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableEvent_0_31(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->EMR1, ExtiLine); +} + +/** + * @brief Disable ExtiLine Event request for Lines in range 32 to 63 + * @rmtoll EMR2 EMx LL_EXTI_DisableEvent_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_32 + * @arg @ref LL_EXTI_LINE_33 + * @arg @ref LL_EXTI_LINE_34(*) + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @arg @ref LL_EXTI_LINE_39(*) + * @arg @ref LL_EXTI_LINE_40(*) + * @arg @ref LL_EXTI_LINE_ALL_32_63 + * @note (*): Available in some devices + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableEvent_32_63(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->EMR2, ExtiLine); +} + +/** + * @brief Indicate if ExtiLine Event request is enabled for Lines in range 0 to 31 + * @rmtoll EMR1 EMx LL_EXTI_IsEnabledEvent_0_31 + * @param ExtiLine This parameter can be one of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_17 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_23 + * @arg @ref LL_EXTI_LINE_24 + * @arg @ref LL_EXTI_LINE_25 + * @arg @ref LL_EXTI_LINE_26 + * @arg @ref LL_EXTI_LINE_27 + * @arg @ref LL_EXTI_LINE_28 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @arg @ref LL_EXTI_LINE_ALL_0_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledEvent_0_31(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->EMR1, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); + +} + +/** + * @brief Indicate if ExtiLine Event request is enabled for Lines in range 32 to 63 + * @rmtoll EMR2 EMx LL_EXTI_IsEnabledEvent_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_32 + * @arg @ref LL_EXTI_LINE_33 + * @arg @ref LL_EXTI_LINE_34(*) + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @arg @ref LL_EXTI_LINE_39(*) + * @arg @ref LL_EXTI_LINE_40(*) + * @arg @ref LL_EXTI_LINE_ALL_32_63 + * @note (*): Available in some devices + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledEvent_32_63(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->EMR2, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup EXTI_LL_EF_Rising_Trigger_Management Rising_Trigger_Management + * @{ + */ + +/** + * @brief Enable ExtiLine Rising Edge Trigger for Lines in range 0 to 31 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a rising edge on a configurable interrupt + * line occurs during a write operation in the EXTI_RTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for + * the same interrupt line. In this case, both generate a trigger + * condition. + * @rmtoll RTSR1 RTx LL_EXTI_EnableRisingTrig_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableRisingTrig_0_31(uint32_t ExtiLine) +{ + SET_BIT(EXTI->RTSR1, ExtiLine); + +} + +/** + * @brief Enable ExtiLine Rising Edge Trigger for Lines in range 32 to 63 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a rising edge on a configurable interrupt + * line occurs during a write operation in the EXTI_RTSR register, the + * pending bit is not set.Rising and falling edge triggers can be set for + * the same interrupt line. In this case, both generate a trigger + * condition. + * @rmtoll RTSR2 RTx LL_EXTI_EnableRisingTrig_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableRisingTrig_32_63(uint32_t ExtiLine) +{ + SET_BIT(EXTI->RTSR2, ExtiLine); +} + +/** + * @brief Disable ExtiLine Rising Edge Trigger for Lines in range 0 to 31 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a rising edge on a configurable interrupt + * line occurs during a write operation in the EXTI_RTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for + * the same interrupt line. In this case, both generate a trigger + * condition. + * @rmtoll RTSR1 RTx LL_EXTI_DisableRisingTrig_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableRisingTrig_0_31(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->RTSR1, ExtiLine); + +} + +/** + * @brief Disable ExtiLine Rising Edge Trigger for Lines in range 32 to 63 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a rising edge on a configurable interrupt + * line occurs during a write operation in the EXTI_RTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for + * the same interrupt line. In this case, both generate a trigger + * condition. + * @rmtoll RTSR2 RTx LL_EXTI_DisableRisingTrig_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableRisingTrig_32_63(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->RTSR2, ExtiLine); +} + +/** + * @brief Check if rising edge trigger is enabled for Lines in range 0 to 31 + * @rmtoll RTSR1 RTx LL_EXTI_IsEnabledRisingTrig_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledRisingTrig_0_31(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->RTSR1, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @brief Check if rising edge trigger is enabled for Lines in range 32 to 63 + * @rmtoll RTSR2 RTx LL_EXTI_IsEnabledRisingTrig_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledRisingTrig_32_63(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->RTSR2, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup EXTI_LL_EF_Falling_Trigger_Management Falling_Trigger_Management + * @{ + */ + +/** + * @brief Enable ExtiLine Falling Edge Trigger for Lines in range 0 to 31 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a falling edge on a configurable interrupt + * line occurs during a write operation in the EXTI_FTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for + * the same interrupt line. In this case, both generate a trigger + * condition. + * @rmtoll FTSR1 FTx LL_EXTI_EnableFallingTrig_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableFallingTrig_0_31(uint32_t ExtiLine) +{ + SET_BIT(EXTI->FTSR1, ExtiLine); +} + +/** + * @brief Enable ExtiLine Falling Edge Trigger for Lines in range 32 to 63 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a Falling edge on a configurable interrupt + * line occurs during a write operation in the EXTI_FTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for + * the same interrupt line. In this case, both generate a trigger + * condition. + * @rmtoll FTSR2 FTx LL_EXTI_EnableFallingTrig_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval None + */ +__STATIC_INLINE void LL_EXTI_EnableFallingTrig_32_63(uint32_t ExtiLine) +{ + SET_BIT(EXTI->FTSR2, ExtiLine); +} + +/** + * @brief Disable ExtiLine Falling Edge Trigger for Lines in range 0 to 31 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a Falling edge on a configurable interrupt + * line occurs during a write operation in the EXTI_FTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for the same interrupt line. + * In this case, both generate a trigger condition. + * @rmtoll FTSR1 FTx LL_EXTI_DisableFallingTrig_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableFallingTrig_0_31(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->FTSR1, ExtiLine); +} + +/** + * @brief Disable ExtiLine Falling Edge Trigger for Lines in range 32 to 63 + * @note The configurable wakeup lines are edge-triggered. No glitch must be + * generated on these lines. If a Falling edge on a configurable interrupt + * line occurs during a write operation in the EXTI_FTSR register, the + * pending bit is not set. + * Rising and falling edge triggers can be set for the same interrupt line. + * In this case, both generate a trigger condition. + * @rmtoll FTSR2 FTx LL_EXTI_DisableFallingTrig_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval None + */ +__STATIC_INLINE void LL_EXTI_DisableFallingTrig_32_63(uint32_t ExtiLine) +{ + CLEAR_BIT(EXTI->FTSR2, ExtiLine); +} + +/** + * @brief Check if falling edge trigger is enabled for Lines in range 0 to 31 + * @rmtoll FTSR1 FTx LL_EXTI_IsEnabledFallingTrig_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledFallingTrig_0_31(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->FTSR1, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @brief Check if falling edge trigger is enabled for Lines in range 32 to 63 + * @rmtoll FTSR2 FTx LL_EXTI_IsEnabledFallingTrig_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsEnabledFallingTrig_32_63(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->FTSR2, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup EXTI_LL_EF_Software_Interrupt_Management Software_Interrupt_Management + * @{ + */ + +/** + * @brief Generate a software Interrupt Event for Lines in range 0 to 31 + * @note If the interrupt is enabled on this line in the EXTI_IMR1, writing a 1 to + * this bit when it is at '0' sets the corresponding pending bit in EXTI_PR1 + * resulting in an interrupt request generation. + * This bit is cleared by clearing the corresponding bit in the EXTI_PR1 + * register (by writing a 1 into the bit) + * @rmtoll SWIER1 SWIx LL_EXTI_GenerateSWI_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_GenerateSWI_0_31(uint32_t ExtiLine) +{ + SET_BIT(EXTI->SWIER1, ExtiLine); +} + +/** + * @brief Generate a software Interrupt Event for Lines in range 32 to 63 + * @note If the interrupt is enabled on this line in the EXTI_IMR2, writing a 1 to + * this bit when it is at '0' sets the corresponding pending bit in EXTI_PR2 + * resulting in an interrupt request generation. + * This bit is cleared by clearing the corresponding bit in the EXTI_PR2 + * register (by writing a 1 into the bit) + * @rmtoll SWIER2 SWIx LL_EXTI_GenerateSWI_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval None + */ +__STATIC_INLINE void LL_EXTI_GenerateSWI_32_63(uint32_t ExtiLine) +{ + SET_BIT(EXTI->SWIER2, ExtiLine); +} + +/** + * @} + */ + +/** @defgroup EXTI_LL_EF_Flag_Management Flag_Management + * @{ + */ + +/** + * @brief Check if the ExtLine Flag is set or not for Lines in range 0 to 31 + * @note This bit is set when the selected edge event arrives on the interrupt + * line. This bit is cleared by writing a 1 to the bit. + * @rmtoll PR1 PIFx LL_EXTI_IsActiveFlag_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsActiveFlag_0_31(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->PR1, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @brief Check if the ExtLine Flag is set or not for Lines in range 32 to 63 + * @note This bit is set when the selected edge event arrives on the interrupt + * line. This bit is cleared by writing a 1 to the bit. + * @rmtoll PR2 PIFx LL_EXTI_IsActiveFlag_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_EXTI_IsActiveFlag_32_63(uint32_t ExtiLine) +{ + return ((READ_BIT(EXTI->PR2, ExtiLine) == (ExtiLine)) ? 1UL : 0UL); +} + +/** + * @brief Read ExtLine Combination Flag for Lines in range 0 to 31 + * @note This bit is set when the selected edge event arrives on the interrupt + * line. This bit is cleared by writing a 1 to the bit. + * @rmtoll PR1 PIFx LL_EXTI_ReadFlag_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval @note This bit is set when the selected edge event arrives on the interrupt + */ +__STATIC_INLINE uint32_t LL_EXTI_ReadFlag_0_31(uint32_t ExtiLine) +{ + return (uint32_t)(READ_BIT(EXTI->PR1, ExtiLine)); +} + +/** + * @brief Read ExtLine Combination Flag for Lines in range 32 to 63 + * @note This bit is set when the selected edge event arrives on the interrupt + * line. This bit is cleared by writing a 1 to the bit. + * @rmtoll PR2 PIFx LL_EXTI_ReadFlag_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval @note This bit is set when the selected edge event arrives on the interrupt + */ +__STATIC_INLINE uint32_t LL_EXTI_ReadFlag_32_63(uint32_t ExtiLine) +{ + return (uint32_t)(READ_BIT(EXTI->PR2, ExtiLine)); +} + +/** + * @brief Clear ExtLine Flags for Lines in range 0 to 31 + * @note This bit is set when the selected edge event arrives on the interrupt + * line. This bit is cleared by writing a 1 to the bit. + * @rmtoll PR1 PIFx LL_EXTI_ClearFlag_0_31 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_0 + * @arg @ref LL_EXTI_LINE_1 + * @arg @ref LL_EXTI_LINE_2 + * @arg @ref LL_EXTI_LINE_3 + * @arg @ref LL_EXTI_LINE_4 + * @arg @ref LL_EXTI_LINE_5 + * @arg @ref LL_EXTI_LINE_6 + * @arg @ref LL_EXTI_LINE_7 + * @arg @ref LL_EXTI_LINE_8 + * @arg @ref LL_EXTI_LINE_9 + * @arg @ref LL_EXTI_LINE_10 + * @arg @ref LL_EXTI_LINE_11 + * @arg @ref LL_EXTI_LINE_12 + * @arg @ref LL_EXTI_LINE_13 + * @arg @ref LL_EXTI_LINE_14 + * @arg @ref LL_EXTI_LINE_15 + * @arg @ref LL_EXTI_LINE_16 + * @arg @ref LL_EXTI_LINE_18 + * @arg @ref LL_EXTI_LINE_19 + * @arg @ref LL_EXTI_LINE_20 + * @arg @ref LL_EXTI_LINE_21 + * @arg @ref LL_EXTI_LINE_22 + * @arg @ref LL_EXTI_LINE_29 + * @arg @ref LL_EXTI_LINE_30 + * @arg @ref LL_EXTI_LINE_31 + * @note Please check each device line mapping for EXTI Line availability + * @retval None + */ +__STATIC_INLINE void LL_EXTI_ClearFlag_0_31(uint32_t ExtiLine) +{ + WRITE_REG(EXTI->PR1, ExtiLine); +} + +/** + * @brief Clear ExtLine Flags for Lines in range 32 to 63 + * @note This bit is set when the selected edge event arrives on the interrupt + * line. This bit is cleared by writing a 1 to the bit. + * @rmtoll PR2 PIFx LL_EXTI_ClearFlag_32_63 + * @param ExtiLine This parameter can be a combination of the following values: + * @arg @ref LL_EXTI_LINE_35 + * @arg @ref LL_EXTI_LINE_36 + * @arg @ref LL_EXTI_LINE_37 + * @arg @ref LL_EXTI_LINE_38 + * @retval None + */ +__STATIC_INLINE void LL_EXTI_ClearFlag_32_63(uint32_t ExtiLine) +{ + WRITE_REG(EXTI->PR2, ExtiLine); +} + + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup EXTI_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +uint32_t LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct); +uint32_t LL_EXTI_DeInit(void); +void LL_EXTI_StructInit(LL_EXTI_InitTypeDef *EXTI_InitStruct); + + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* EXTI */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_EXTI_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_gpio.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_gpio.h new file mode 100644 index 0000000..72bb307 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_gpio.h @@ -0,0 +1,1056 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_gpio.h + * @author MCD Application Team + * @brief Header file of GPIO 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 STM32L4xx_LL_GPIO_H +#define STM32L4xx_LL_GPIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) + +/** @defgroup GPIO_LL GPIO + * @{ + */ +/** MISRA C:2012 deviation rule has been granted for following rules: + * Rule-18.1_d - Medium: Array pointer `GPIOx' is accessed with index [..,..] + * which may be out of array bounds [..,UNKNOWN] in following APIs: + * LL_GPIO_GetAFPin_0_7 + * LL_GPIO_SetAFPin_0_7 + * LL_GPIO_SetAFPin_8_15 + * LL_GPIO_GetAFPin_8_15 + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup GPIO_LL_Private_Macros GPIO Private Macros + * @{ + */ + +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup GPIO_LL_ES_INIT GPIO Exported Init structures + * @{ + */ + +/** + * @brief LL GPIO Init Structure definition + */ +typedef struct +{ + uint32_t Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_LL_EC_PIN */ + + uint32_t Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIO_LL_EC_MODE. + + GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinMode().*/ + + uint32_t Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIO_LL_EC_SPEED. + + GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinSpeed().*/ + + uint32_t OutputType; /*!< Specifies the operating output type for the selected pins. + This parameter can be a value of @ref GPIO_LL_EC_OUTPUT. + + GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinOutputType().*/ + + uint32_t Pull; /*!< Specifies the operating Pull-up/Pull down for the selected pins. + This parameter can be a value of @ref GPIO_LL_EC_PULL. + + GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetPinPull().*/ + + uint32_t Alternate; /*!< Specifies the Peripheral to be connected to the selected pins. + This parameter can be a value of @ref GPIO_LL_EC_AF. + + GPIO HW configuration can be modified afterwards using unitary function @ref LL_GPIO_SetAFPin_0_7() and LL_GPIO_SetAFPin_8_15().*/ +} LL_GPIO_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIO_LL_Exported_Constants GPIO Exported Constants + * @{ + */ + +/** @defgroup GPIO_LL_EC_PIN PIN + * @{ + */ +#define LL_GPIO_PIN_0 GPIO_BSRR_BS0 /*!< Select pin 0 */ +#define LL_GPIO_PIN_1 GPIO_BSRR_BS1 /*!< Select pin 1 */ +#define LL_GPIO_PIN_2 GPIO_BSRR_BS2 /*!< Select pin 2 */ +#define LL_GPIO_PIN_3 GPIO_BSRR_BS3 /*!< Select pin 3 */ +#define LL_GPIO_PIN_4 GPIO_BSRR_BS4 /*!< Select pin 4 */ +#define LL_GPIO_PIN_5 GPIO_BSRR_BS5 /*!< Select pin 5 */ +#define LL_GPIO_PIN_6 GPIO_BSRR_BS6 /*!< Select pin 6 */ +#define LL_GPIO_PIN_7 GPIO_BSRR_BS7 /*!< Select pin 7 */ +#define LL_GPIO_PIN_8 GPIO_BSRR_BS8 /*!< Select pin 8 */ +#define LL_GPIO_PIN_9 GPIO_BSRR_BS9 /*!< Select pin 9 */ +#define LL_GPIO_PIN_10 GPIO_BSRR_BS10 /*!< Select pin 10 */ +#define LL_GPIO_PIN_11 GPIO_BSRR_BS11 /*!< Select pin 11 */ +#define LL_GPIO_PIN_12 GPIO_BSRR_BS12 /*!< Select pin 12 */ +#define LL_GPIO_PIN_13 GPIO_BSRR_BS13 /*!< Select pin 13 */ +#define LL_GPIO_PIN_14 GPIO_BSRR_BS14 /*!< Select pin 14 */ +#define LL_GPIO_PIN_15 GPIO_BSRR_BS15 /*!< Select pin 15 */ +#define LL_GPIO_PIN_ALL (GPIO_BSRR_BS0 | GPIO_BSRR_BS1 | GPIO_BSRR_BS2 | \ + GPIO_BSRR_BS3 | GPIO_BSRR_BS4 | GPIO_BSRR_BS5 | \ + GPIO_BSRR_BS6 | GPIO_BSRR_BS7 | GPIO_BSRR_BS8 | \ + GPIO_BSRR_BS9 | GPIO_BSRR_BS10 | GPIO_BSRR_BS11 | \ + GPIO_BSRR_BS12 | GPIO_BSRR_BS13 | GPIO_BSRR_BS14 | \ + GPIO_BSRR_BS15) /*!< Select all pins */ +/** + * @} + */ + +/** @defgroup GPIO_LL_EC_MODE Mode + * @{ + */ +#define LL_GPIO_MODE_INPUT (0x00000000U) /*!< Select input mode */ +#define LL_GPIO_MODE_OUTPUT GPIO_MODER_MODE0_0 /*!< Select output mode */ +#define LL_GPIO_MODE_ALTERNATE GPIO_MODER_MODE0_1 /*!< Select alternate function mode */ +#define LL_GPIO_MODE_ANALOG GPIO_MODER_MODE0 /*!< Select analog mode */ +/** + * @} + */ + +/** @defgroup GPIO_LL_EC_OUTPUT Output Type + * @{ + */ +#define LL_GPIO_OUTPUT_PUSHPULL (0x00000000U) /*!< Select push-pull as output type */ +#define LL_GPIO_OUTPUT_OPENDRAIN GPIO_OTYPER_OT0 /*!< Select open-drain as output type */ +/** + * @} + */ + +/** @defgroup GPIO_LL_EC_SPEED Output Speed + * @{ + */ +#define LL_GPIO_SPEED_FREQ_LOW (0x00000000U) /*!< Select I/O low output speed */ +#define LL_GPIO_SPEED_FREQ_MEDIUM GPIO_OSPEEDR_OSPEED0_0 /*!< Select I/O medium output speed */ +#define LL_GPIO_SPEED_FREQ_HIGH GPIO_OSPEEDR_OSPEED0_1 /*!< Select I/O fast output speed */ +#define LL_GPIO_SPEED_FREQ_VERY_HIGH GPIO_OSPEEDR_OSPEED0 /*!< Select I/O high output speed */ +/** + * @} + */ +#define LL_GPIO_SPEED_LOW LL_GPIO_SPEED_FREQ_LOW +#define LL_GPIO_SPEED_MEDIUM LL_GPIO_SPEED_FREQ_MEDIUM +#define LL_GPIO_SPEED_FAST LL_GPIO_SPEED_FREQ_HIGH +#define LL_GPIO_SPEED_HIGH LL_GPIO_SPEED_FREQ_VERY_HIGH + +/** @defgroup GPIO_LL_EC_PULL Pull Up Pull Down + * @{ + */ +#define LL_GPIO_PULL_NO (0x00000000U) /*!< Select I/O no pull */ +#define LL_GPIO_PULL_UP GPIO_PUPDR_PUPD0_0 /*!< Select I/O pull up */ +#define LL_GPIO_PULL_DOWN GPIO_PUPDR_PUPD0_1 /*!< Select I/O pull down */ +/** + * @} + */ + +/** @defgroup GPIO_LL_EC_AF Alternate Function + * @{ + */ +#define LL_GPIO_AF_0 (0x0000000U) /*!< Select alternate function 0 */ +#define LL_GPIO_AF_1 (0x0000001U) /*!< Select alternate function 1 */ +#define LL_GPIO_AF_2 (0x0000002U) /*!< Select alternate function 2 */ +#define LL_GPIO_AF_3 (0x0000003U) /*!< Select alternate function 3 */ +#define LL_GPIO_AF_4 (0x0000004U) /*!< Select alternate function 4 */ +#define LL_GPIO_AF_5 (0x0000005U) /*!< Select alternate function 5 */ +#define LL_GPIO_AF_6 (0x0000006U) /*!< Select alternate function 6 */ +#define LL_GPIO_AF_7 (0x0000007U) /*!< Select alternate function 7 */ +#define LL_GPIO_AF_8 (0x0000008U) /*!< Select alternate function 8 */ +#define LL_GPIO_AF_9 (0x0000009U) /*!< Select alternate function 9 */ +#define LL_GPIO_AF_10 (0x000000AU) /*!< Select alternate function 10 */ +#define LL_GPIO_AF_11 (0x000000BU) /*!< Select alternate function 11 */ +#define LL_GPIO_AF_12 (0x000000CU) /*!< Select alternate function 12 */ +#define LL_GPIO_AF_13 (0x000000DU) /*!< Select alternate function 13 */ +#define LL_GPIO_AF_14 (0x000000EU) /*!< Select alternate function 14 */ +#define LL_GPIO_AF_15 (0x000000FU) /*!< Select alternate function 15 */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIO_LL_Exported_Macros GPIO Exported Macros + * @{ + */ + +/** @defgroup GPIO_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in GPIO register + * @param __INSTANCE__ GPIO Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_GPIO_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in GPIO register + * @param __INSTANCE__ GPIO Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_GPIO_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup GPIO_LL_Exported_Functions GPIO Exported Functions + * @{ + */ + +/** @defgroup GPIO_LL_EF_Port_Configuration Port Configuration + * @{ + */ + +/** + * @brief Configure gpio mode for a dedicated pin on dedicated port. + * @note I/O mode can be Input mode, General purpose output, Alternate function mode or Analog. + * @note Warning: only one pin can be passed as parameter. + * @rmtoll MODER MODEy LL_GPIO_SetPinMode + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_GPIO_MODE_INPUT + * @arg @ref LL_GPIO_MODE_OUTPUT + * @arg @ref LL_GPIO_MODE_ALTERNATE + * @arg @ref LL_GPIO_MODE_ANALOG + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetPinMode(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Mode) +{ + MODIFY_REG(GPIOx->MODER, (GPIO_MODER_MODE0 << (POSITION_VAL(Pin) * 2U)), (Mode << (POSITION_VAL(Pin) * 2U))); +} + +/** + * @brief Return gpio mode for a dedicated pin on dedicated port. + * @note I/O mode can be Input mode, General purpose output, Alternate function mode or Analog. + * @note Warning: only one pin can be passed as parameter. + * @rmtoll MODER MODEy LL_GPIO_GetPinMode + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @retval Returned value can be one of the following values: + * @arg @ref LL_GPIO_MODE_INPUT + * @arg @ref LL_GPIO_MODE_OUTPUT + * @arg @ref LL_GPIO_MODE_ALTERNATE + * @arg @ref LL_GPIO_MODE_ANALOG + */ +__STATIC_INLINE uint32_t LL_GPIO_GetPinMode(GPIO_TypeDef *GPIOx, uint32_t Pin) +{ + return (uint32_t)(READ_BIT(GPIOx->MODER, + (GPIO_MODER_MODE0 << (POSITION_VAL(Pin) * 2U))) >> (POSITION_VAL(Pin) * 2U)); +} + +/** + * @brief Configure gpio output type for several pins on dedicated port. + * @note Output type as to be set when gpio pin is in output or + * alternate modes. Possible type are Push-pull or Open-drain. + * @rmtoll OTYPER OTy LL_GPIO_SetPinOutputType + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @param OutputType This parameter can be one of the following values: + * @arg @ref LL_GPIO_OUTPUT_PUSHPULL + * @arg @ref LL_GPIO_OUTPUT_OPENDRAIN + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetPinOutputType(GPIO_TypeDef *GPIOx, uint32_t PinMask, uint32_t OutputType) +{ + MODIFY_REG(GPIOx->OTYPER, PinMask, (PinMask * OutputType)); +} + +/** + * @brief Return gpio output type for several pins on dedicated port. + * @note Output type as to be set when gpio pin is in output or + * alternate modes. Possible type are Push-pull or Open-drain. + * @note Warning: only one pin can be passed as parameter. + * @rmtoll OTYPER OTy LL_GPIO_GetPinOutputType + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval Returned value can be one of the following values: + * @arg @ref LL_GPIO_OUTPUT_PUSHPULL + * @arg @ref LL_GPIO_OUTPUT_OPENDRAIN + */ +__STATIC_INLINE uint32_t LL_GPIO_GetPinOutputType(GPIO_TypeDef *GPIOx, uint32_t Pin) +{ + return (uint32_t)(READ_BIT(GPIOx->OTYPER, Pin) >> POSITION_VAL(Pin)); +} + +/** + * @brief Configure gpio speed for a dedicated pin on dedicated port. + * @note I/O speed can be Low, Medium, Fast or High speed. + * @note Warning: only one pin can be passed as parameter. + * @note Refer to datasheet for frequency specifications and the power + * supply and load conditions for each speed. + * @rmtoll OSPEEDR OSPEEDy LL_GPIO_SetPinSpeed + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @param Speed This parameter can be one of the following values: + * @arg @ref LL_GPIO_SPEED_FREQ_LOW + * @arg @ref LL_GPIO_SPEED_FREQ_MEDIUM + * @arg @ref LL_GPIO_SPEED_FREQ_HIGH + * @arg @ref LL_GPIO_SPEED_FREQ_VERY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetPinSpeed(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Speed) +{ + MODIFY_REG(GPIOx->OSPEEDR, (GPIO_OSPEEDR_OSPEED0 << (POSITION_VAL(Pin) * 2U)), + (Speed << (POSITION_VAL(Pin) * 2U))); +} + +/** + * @brief Return gpio speed for a dedicated pin on dedicated port. + * @note I/O speed can be Low, Medium, Fast or High speed. + * @note Warning: only one pin can be passed as parameter. + * @note Refer to datasheet for frequency specifications and the power + * supply and load conditions for each speed. + * @rmtoll OSPEEDR OSPEEDy LL_GPIO_GetPinSpeed + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @retval Returned value can be one of the following values: + * @arg @ref LL_GPIO_SPEED_FREQ_LOW + * @arg @ref LL_GPIO_SPEED_FREQ_MEDIUM + * @arg @ref LL_GPIO_SPEED_FREQ_HIGH + * @arg @ref LL_GPIO_SPEED_FREQ_VERY_HIGH + */ +__STATIC_INLINE uint32_t LL_GPIO_GetPinSpeed(GPIO_TypeDef *GPIOx, uint32_t Pin) +{ + return (uint32_t)(READ_BIT(GPIOx->OSPEEDR, + (GPIO_OSPEEDR_OSPEED0 << (POSITION_VAL(Pin) * 2U))) >> (POSITION_VAL(Pin) * 2U)); +} + +/** + * @brief Configure gpio pull-up or pull-down for a dedicated pin on a dedicated port. + * @note Warning: only one pin can be passed as parameter. + * @rmtoll PUPDR PUPDy LL_GPIO_SetPinPull + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @param Pull This parameter can be one of the following values: + * @arg @ref LL_GPIO_PULL_NO + * @arg @ref LL_GPIO_PULL_UP + * @arg @ref LL_GPIO_PULL_DOWN + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Pull) +{ + MODIFY_REG(GPIOx->PUPDR, (GPIO_PUPDR_PUPD0 << (POSITION_VAL(Pin) * 2U)), (Pull << (POSITION_VAL(Pin) * 2U))); +} + +/** + * @brief Return gpio pull-up or pull-down for a dedicated pin on a dedicated port + * @note Warning: only one pin can be passed as parameter. + * @rmtoll PUPDR PUPDy LL_GPIO_GetPinPull + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @retval Returned value can be one of the following values: + * @arg @ref LL_GPIO_PULL_NO + * @arg @ref LL_GPIO_PULL_UP + * @arg @ref LL_GPIO_PULL_DOWN + */ +__STATIC_INLINE uint32_t LL_GPIO_GetPinPull(GPIO_TypeDef *GPIOx, uint32_t Pin) +{ + return (uint32_t)(READ_BIT(GPIOx->PUPDR, + (GPIO_PUPDR_PUPD0 << (POSITION_VAL(Pin) * 2U))) >> (POSITION_VAL(Pin) * 2U)); +} + +/** + * @brief Configure gpio alternate function of a dedicated pin from 0 to 7 for a dedicated port. + * @note Possible values are from AF0 to AF15 depending on target. + * @note Warning: only one pin can be passed as parameter. + * @rmtoll AFRL AFSELy LL_GPIO_SetAFPin_0_7 + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @param Alternate This parameter can be one of the following values: + * @arg @ref LL_GPIO_AF_0 + * @arg @ref LL_GPIO_AF_1 + * @arg @ref LL_GPIO_AF_2 + * @arg @ref LL_GPIO_AF_3 + * @arg @ref LL_GPIO_AF_4 + * @arg @ref LL_GPIO_AF_5 + * @arg @ref LL_GPIO_AF_6 + * @arg @ref LL_GPIO_AF_7 + * @arg @ref LL_GPIO_AF_8 + * @arg @ref LL_GPIO_AF_9 + * @arg @ref LL_GPIO_AF_10 + * @arg @ref LL_GPIO_AF_11 + * @arg @ref LL_GPIO_AF_12 + * @arg @ref LL_GPIO_AF_13 + * @arg @ref LL_GPIO_AF_14 + * @arg @ref LL_GPIO_AF_15 + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetAFPin_0_7(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Alternate) +{ + MODIFY_REG(GPIOx->AFR[0], (GPIO_AFRL_AFSEL0 << (POSITION_VAL(Pin) * 4U)), + (Alternate << (POSITION_VAL(Pin) * 4U))); +} + +/** + * @brief Return gpio alternate function of a dedicated pin from 0 to 7 for a dedicated port. + * @rmtoll AFRL AFSELy LL_GPIO_GetAFPin_0_7 + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @retval Returned value can be one of the following values: + * @arg @ref LL_GPIO_AF_0 + * @arg @ref LL_GPIO_AF_1 + * @arg @ref LL_GPIO_AF_2 + * @arg @ref LL_GPIO_AF_3 + * @arg @ref LL_GPIO_AF_4 + * @arg @ref LL_GPIO_AF_5 + * @arg @ref LL_GPIO_AF_6 + * @arg @ref LL_GPIO_AF_7 + * @arg @ref LL_GPIO_AF_8 + * @arg @ref LL_GPIO_AF_9 + * @arg @ref LL_GPIO_AF_10 + * @arg @ref LL_GPIO_AF_11 + * @arg @ref LL_GPIO_AF_12 + * @arg @ref LL_GPIO_AF_13 + * @arg @ref LL_GPIO_AF_14 + * @arg @ref LL_GPIO_AF_15 + */ +__STATIC_INLINE uint32_t LL_GPIO_GetAFPin_0_7(GPIO_TypeDef *GPIOx, uint32_t Pin) +{ + return (uint32_t)(READ_BIT(GPIOx->AFR[0], + (GPIO_AFRL_AFSEL0 << (POSITION_VAL(Pin) * 4U))) >> (POSITION_VAL(Pin) * 4U)); +} + +/** + * @brief Configure gpio alternate function of a dedicated pin from 8 to 15 for a dedicated port. + * @note Possible values are from AF0 to AF15 depending on target. + * @note Warning: only one pin can be passed as parameter. + * @rmtoll AFRH AFSELy LL_GPIO_SetAFPin_8_15 + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @param Alternate This parameter can be one of the following values: + * @arg @ref LL_GPIO_AF_0 + * @arg @ref LL_GPIO_AF_1 + * @arg @ref LL_GPIO_AF_2 + * @arg @ref LL_GPIO_AF_3 + * @arg @ref LL_GPIO_AF_4 + * @arg @ref LL_GPIO_AF_5 + * @arg @ref LL_GPIO_AF_6 + * @arg @ref LL_GPIO_AF_7 + * @arg @ref LL_GPIO_AF_8 + * @arg @ref LL_GPIO_AF_9 + * @arg @ref LL_GPIO_AF_10 + * @arg @ref LL_GPIO_AF_11 + * @arg @ref LL_GPIO_AF_12 + * @arg @ref LL_GPIO_AF_13 + * @arg @ref LL_GPIO_AF_14 + * @arg @ref LL_GPIO_AF_15 + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetAFPin_8_15(GPIO_TypeDef *GPIOx, uint32_t Pin, uint32_t Alternate) +{ + MODIFY_REG(GPIOx->AFR[1], (GPIO_AFRH_AFSEL8 << (POSITION_VAL(Pin >> 8U) * 4U)), + (Alternate << (POSITION_VAL(Pin >> 8U) * 4U))); +} + +/** + * @brief Return gpio alternate function of a dedicated pin from 8 to 15 for a dedicated port. + * @note Possible values are from AF0 to AF15 depending on target. + * @rmtoll AFRH AFSELy LL_GPIO_GetAFPin_8_15 + * @param GPIOx GPIO Port + * @param Pin This parameter can be one of the following values: + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @retval Returned value can be one of the following values: + * @arg @ref LL_GPIO_AF_0 + * @arg @ref LL_GPIO_AF_1 + * @arg @ref LL_GPIO_AF_2 + * @arg @ref LL_GPIO_AF_3 + * @arg @ref LL_GPIO_AF_4 + * @arg @ref LL_GPIO_AF_5 + * @arg @ref LL_GPIO_AF_6 + * @arg @ref LL_GPIO_AF_7 + * @arg @ref LL_GPIO_AF_8 + * @arg @ref LL_GPIO_AF_9 + * @arg @ref LL_GPIO_AF_10 + * @arg @ref LL_GPIO_AF_11 + * @arg @ref LL_GPIO_AF_12 + * @arg @ref LL_GPIO_AF_13 + * @arg @ref LL_GPIO_AF_14 + * @arg @ref LL_GPIO_AF_15 + */ +__STATIC_INLINE uint32_t LL_GPIO_GetAFPin_8_15(GPIO_TypeDef *GPIOx, uint32_t Pin) +{ + return (uint32_t)(READ_BIT(GPIOx->AFR[1], + (GPIO_AFRH_AFSEL8 << (POSITION_VAL(Pin >> 8U) * 4U))) >> (POSITION_VAL(Pin >> 8U) * 4U)); +} + +#if defined(GPIO_ASCR_ASC0) +/** + * @brief Connect analog switch to ADC input of several pins for a dedicated port. + * @note This bit must be set prior to the ADC conversion. + * Only the IO which connected to the ADC input are effective. + * Other IO must be kept reset value + * @rmtoll ASCR ASCy LL_GPIO_EnablePinAnalogControl + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval None + */ +__STATIC_INLINE void LL_GPIO_EnablePinAnalogControl(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + SET_BIT(GPIOx->ASCR, PinMask); +} + +/** + * @brief Disconnect analog switch to ADC input of several pins for a dedicated port. + * @rmtoll ASCR ASCy LL_GPIO_DisablePinAnalogControl + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval None + */ +__STATIC_INLINE void LL_GPIO_DisablePinAnalogControl(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + CLEAR_BIT(GPIOx->ASCR, PinMask); +} +#endif /* GPIO_ASCR_ASC0 */ + +/** + * @brief Lock configuration of several pins for a dedicated port. + * @note When the lock sequence has been applied on a port bit, the + * value of this port bit can no longer be modified until the + * next reset. + * @note Each lock bit freezes a specific configuration register + * (control and alternate function registers). + * @rmtoll LCKR LCKK LL_GPIO_LockPin + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval None + */ +__STATIC_INLINE void LL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + __IO uint32_t temp; + WRITE_REG(GPIOx->LCKR, GPIO_LCKR_LCKK | PinMask); + WRITE_REG(GPIOx->LCKR, PinMask); + WRITE_REG(GPIOx->LCKR, GPIO_LCKR_LCKK | PinMask); + /* Read LCKK register. This read is mandatory to complete key lock sequence */ + temp = READ_REG(GPIOx->LCKR); + (void) temp; +} + +/** + * @brief Return 1 if all pins passed as parameter, of a dedicated port, are locked. else Return 0. + * @rmtoll LCKR LCKy LL_GPIO_IsPinLocked + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_GPIO_IsPinLocked(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + return ((READ_BIT(GPIOx->LCKR, PinMask) == (PinMask)) ? 1UL : 0UL); +} + +/** + * @brief Return 1 if one of the pin of a dedicated port is locked. else return 0. + * @rmtoll LCKR LCKK LL_GPIO_IsAnyPinLocked + * @param GPIOx GPIO Port + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_GPIO_IsAnyPinLocked(GPIO_TypeDef *GPIOx) +{ + return ((READ_BIT(GPIOx->LCKR, GPIO_LCKR_LCKK) == (GPIO_LCKR_LCKK)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup GPIO_LL_EF_Data_Access Data Access + * @{ + */ + +/** + * @brief Return full input data register value for a dedicated port. + * @rmtoll IDR IDy LL_GPIO_ReadInputPort + * @param GPIOx GPIO Port + * @retval Input data register value of port + */ +__STATIC_INLINE uint32_t LL_GPIO_ReadInputPort(GPIO_TypeDef *GPIOx) +{ + return (uint32_t)(READ_REG(GPIOx->IDR)); +} + +/** + * @brief Return if input data level for several pins of dedicated port is high or low. + * @rmtoll IDR IDy LL_GPIO_IsInputPinSet + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_GPIO_IsInputPinSet(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + return ((READ_BIT(GPIOx->IDR, PinMask) == (PinMask)) ? 1UL : 0UL); +} + +/** + * @brief Write output data register for the port. + * @rmtoll ODR ODy LL_GPIO_WriteOutputPort + * @param GPIOx GPIO Port + * @param PortValue Level value for each pin of the port + * @retval None + */ +__STATIC_INLINE void LL_GPIO_WriteOutputPort(GPIO_TypeDef *GPIOx, uint32_t PortValue) +{ + WRITE_REG(GPIOx->ODR, PortValue); +} + +/** + * @brief Return full output data register value for a dedicated port. + * @rmtoll ODR ODy LL_GPIO_ReadOutputPort + * @param GPIOx GPIO Port + * @retval Output data register value of port + */ +__STATIC_INLINE uint32_t LL_GPIO_ReadOutputPort(GPIO_TypeDef *GPIOx) +{ + return (uint32_t)(READ_REG(GPIOx->ODR)); +} + +/** + * @brief Return if input data level for several pins of dedicated port is high or low. + * @rmtoll ODR ODy LL_GPIO_IsOutputPinSet + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_GPIO_IsOutputPinSet(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + return ((READ_BIT(GPIOx->ODR, PinMask) == (PinMask)) ? 1UL : 0UL); +} + +/** + * @brief Set several pins to high level on dedicated gpio port. + * @rmtoll BSRR BSy LL_GPIO_SetOutputPin + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval None + */ +__STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + WRITE_REG(GPIOx->BSRR, PinMask); +} + +/** + * @brief Set several pins to low level on dedicated gpio port. + * @rmtoll BRR BRy LL_GPIO_ResetOutputPin + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval None + */ +__STATIC_INLINE void LL_GPIO_ResetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + WRITE_REG(GPIOx->BRR, PinMask); +} + +/** + * @brief Toggle data value for several pin of dedicated port. + * @rmtoll ODR ODy LL_GPIO_TogglePin + * @param GPIOx GPIO Port + * @param PinMask This parameter can be a combination of the following values: + * @arg @ref LL_GPIO_PIN_0 + * @arg @ref LL_GPIO_PIN_1 + * @arg @ref LL_GPIO_PIN_2 + * @arg @ref LL_GPIO_PIN_3 + * @arg @ref LL_GPIO_PIN_4 + * @arg @ref LL_GPIO_PIN_5 + * @arg @ref LL_GPIO_PIN_6 + * @arg @ref LL_GPIO_PIN_7 + * @arg @ref LL_GPIO_PIN_8 + * @arg @ref LL_GPIO_PIN_9 + * @arg @ref LL_GPIO_PIN_10 + * @arg @ref LL_GPIO_PIN_11 + * @arg @ref LL_GPIO_PIN_12 + * @arg @ref LL_GPIO_PIN_13 + * @arg @ref LL_GPIO_PIN_14 + * @arg @ref LL_GPIO_PIN_15 + * @arg @ref LL_GPIO_PIN_ALL + * @retval None + */ +__STATIC_INLINE void LL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint32_t PinMask) +{ + uint32_t odr = READ_REG(GPIOx->ODR); + WRITE_REG(GPIOx->BSRR, ((odr & PinMask) << 16u) | (~odr & PinMask)); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup GPIO_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_GPIO_DeInit(GPIO_TypeDef *GPIOx); +ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct); +void LL_GPIO_StructInit(LL_GPIO_InitTypeDef *GPIO_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) */ +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_GPIO_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h new file mode 100644 index 0000000..5e1b626 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_i2c.h @@ -0,0 +1,2272 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_i2c.h + * @author MCD Application Team + * @brief Header file of I2C 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 STM32L4xx_LL_I2C_H +#define STM32L4xx_LL_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (I2C1) || defined (I2C2) || defined (I2C3) || defined (I2C4) + +/** @defgroup I2C_LL I2C + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2C_LL_Private_Constants I2C Private Constants + * @{ + */ +/** + * @} + */ + +/* 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 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_I2C_CONVERT_TIMINGS(). + + This feature can be modified afterwards using unitary function + @ref LL_I2C_SetTiming(). */ + + 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(). */ + + 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_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_I2C_WriteReg function + * @{ + */ +#define LL_I2C_ICR_ADDRCF I2C_ICR_ADDRCF /*!< Address Matched flag */ +#define LL_I2C_ICR_NACKCF I2C_ICR_NACKCF /*!< Not Acknowledge flag */ +#define LL_I2C_ICR_STOPCF I2C_ICR_STOPCF /*!< Stop detection flag */ +#define LL_I2C_ICR_BERRCF I2C_ICR_BERRCF /*!< Bus error flag */ +#define LL_I2C_ICR_ARLOCF I2C_ICR_ARLOCF /*!< Arbitration Lost flag */ +#define LL_I2C_ICR_OVRCF I2C_ICR_OVRCF /*!< Overrun/Underrun flag */ +#define LL_I2C_ICR_PECCF I2C_ICR_PECCF /*!< PEC error flag */ +#define LL_I2C_ICR_TIMOUTCF I2C_ICR_TIMOUTCF /*!< Timeout detection flag */ +#define LL_I2C_ICR_ALERTCF I2C_ICR_ALERTCF /*!< Alert flag */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_I2C_ReadReg function + * @{ + */ +#define LL_I2C_ISR_TXE I2C_ISR_TXE /*!< Transmit data register empty */ +#define LL_I2C_ISR_TXIS I2C_ISR_TXIS /*!< Transmit interrupt status */ +#define LL_I2C_ISR_RXNE I2C_ISR_RXNE /*!< Receive data register not empty */ +#define LL_I2C_ISR_ADDR I2C_ISR_ADDR /*!< Address matched (slave mode) */ +#define LL_I2C_ISR_NACKF I2C_ISR_NACKF /*!< Not Acknowledge received flag */ +#define LL_I2C_ISR_STOPF I2C_ISR_STOPF /*!< Stop detection flag */ +#define LL_I2C_ISR_TC I2C_ISR_TC /*!< Transfer Complete (master mode) */ +#define LL_I2C_ISR_TCR I2C_ISR_TCR /*!< Transfer Complete Reload */ +#define LL_I2C_ISR_BERR I2C_ISR_BERR /*!< Bus error */ +#define LL_I2C_ISR_ARLO I2C_ISR_ARLO /*!< Arbitration lost */ +#define LL_I2C_ISR_OVR I2C_ISR_OVR /*!< Overrun/Underrun (slave mode) */ +#define LL_I2C_ISR_PECERR I2C_ISR_PECERR /*!< PEC Error in reception (SMBus mode) */ +#define LL_I2C_ISR_TIMEOUT I2C_ISR_TIMEOUT /*!< Timeout detection flag (SMBus mode) */ +#define LL_I2C_ISR_ALERT I2C_ISR_ALERT /*!< SMBus alert (SMBus mode) */ +#define LL_I2C_ISR_BUSY I2C_ISR_BUSY /*!< Bus busy */ +/** + * @} + */ + +/** @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_CR1_TXIE I2C_CR1_TXIE /*!< TX Interrupt enable */ +#define LL_I2C_CR1_RXIE I2C_CR1_RXIE /*!< RX Interrupt enable */ +#define LL_I2C_CR1_ADDRIE I2C_CR1_ADDRIE /*!< Address match Interrupt enable (slave only) */ +#define LL_I2C_CR1_NACKIE I2C_CR1_NACKIE /*!< Not acknowledge received Interrupt enable */ +#define LL_I2C_CR1_STOPIE I2C_CR1_STOPIE /*!< STOP detection Interrupt enable */ +#define LL_I2C_CR1_TCIE I2C_CR1_TCIE /*!< Transfer Complete interrupt enable */ +#define LL_I2C_CR1_ERRIE I2C_CR1_ERRIE /*!< Error interrupts enable */ +/** + * @} + */ + +/** @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 I2C_CR1_SMBHEN /*!< SMBus Host address acknowledge */ +#define LL_I2C_MODE_SMBUS_DEVICE 0x00000000U /*!< SMBus Device default mode + (Default address not acknowledge) */ +#define LL_I2C_MODE_SMBUS_DEVICE_ARP I2C_CR1_SMBDEN /*!< SMBus Device Default address acknowledge */ +/** + * @} + */ + +/** @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_CR1_ANFOFF /*!< Analog filter is disabled. */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_ADDRESSING_MODE Master Addressing Mode + * @{ + */ +#define LL_I2C_ADDRESSING_MODE_7BIT 0x00000000U /*!< Master operates in 7-bit addressing mode. */ +#define LL_I2C_ADDRESSING_MODE_10BIT I2C_CR2_ADD10 /*!< Master operates in 10-bit addressing mode.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_OWNADDRESS1 Own Address 1 Length + * @{ + */ +#define LL_I2C_OWNADDRESS1_7BIT 0x00000000U /*!< Own address 1 is a 7-bit address. */ +#define LL_I2C_OWNADDRESS1_10BIT I2C_OAR1_OA1MODE /*!< Own address 1 is a 10-bit address.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_OWNADDRESS2 Own Address 2 Masks + * @{ + */ +#define LL_I2C_OWNADDRESS2_NOMASK I2C_OAR2_OA2NOMASK /*!< Own Address2 No mask. */ +#define LL_I2C_OWNADDRESS2_MASK01 I2C_OAR2_OA2MASK01 /*!< Only Address2 bits[7:2] are compared. */ +#define LL_I2C_OWNADDRESS2_MASK02 I2C_OAR2_OA2MASK02 /*!< Only Address2 bits[7:3] are compared. */ +#define LL_I2C_OWNADDRESS2_MASK03 I2C_OAR2_OA2MASK03 /*!< Only Address2 bits[7:4] are compared. */ +#define LL_I2C_OWNADDRESS2_MASK04 I2C_OAR2_OA2MASK04 /*!< Only Address2 bits[7:5] are compared. */ +#define LL_I2C_OWNADDRESS2_MASK05 I2C_OAR2_OA2MASK05 /*!< Only Address2 bits[7:6] are compared. */ +#define LL_I2C_OWNADDRESS2_MASK06 I2C_OAR2_OA2MASK06 /*!< Only Address2 bits[7] are compared. */ +#define LL_I2C_OWNADDRESS2_MASK07 I2C_OAR2_OA2MASK07 /*!< No comparison is done. + All Address2 are acknowledged. */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_I2C_ACKNOWLEDGE Acknowledge Generation + * @{ + */ +#define LL_I2C_ACK 0x00000000U /*!< ACK is sent after current received byte. */ +#define LL_I2C_NACK I2C_CR2_NACK /*!< NACK is sent after current received byte.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_ADDRSLAVE Slave Address Length + * @{ + */ +#define LL_I2C_ADDRSLAVE_7BIT 0x00000000U /*!< Slave Address in 7-bit. */ +#define LL_I2C_ADDRSLAVE_10BIT I2C_CR2_ADD10 /*!< Slave Address in 10-bit.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_REQUEST Transfer Request Direction + * @{ + */ +#define LL_I2C_REQUEST_WRITE 0x00000000U /*!< Master request a write transfer. */ +#define LL_I2C_REQUEST_READ I2C_CR2_RD_WRN /*!< Master request a read transfer. */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_MODE Transfer End Mode + * @{ + */ +#define LL_I2C_MODE_RELOAD I2C_CR2_RELOAD /*!< Enable I2C Reload mode. */ +#define LL_I2C_MODE_AUTOEND I2C_CR2_AUTOEND /*!< Enable I2C Automatic end mode + with no HW PEC comparison. */ +#define LL_I2C_MODE_SOFTEND 0x00000000U /*!< Enable I2C Software end mode + with no HW PEC comparison. */ +#define LL_I2C_MODE_SMBUS_RELOAD LL_I2C_MODE_RELOAD /*!< Enable SMBUS Automatic end mode + with HW PEC comparison. */ +#define LL_I2C_MODE_SMBUS_AUTOEND_NO_PEC LL_I2C_MODE_AUTOEND /*!< Enable SMBUS Automatic end mode + with HW PEC comparison. */ +#define LL_I2C_MODE_SMBUS_SOFTEND_NO_PEC LL_I2C_MODE_SOFTEND /*!< Enable SMBUS Software end mode + with HW PEC comparison. */ +#define LL_I2C_MODE_SMBUS_AUTOEND_WITH_PEC (uint32_t)(LL_I2C_MODE_AUTOEND | I2C_CR2_PECBYTE) +/*!< Enable SMBUS Automatic end mode with HW PEC comparison. */ +#define LL_I2C_MODE_SMBUS_SOFTEND_WITH_PEC (uint32_t)(LL_I2C_MODE_SOFTEND | I2C_CR2_PECBYTE) +/*!< Enable SMBUS Software end mode with HW PEC comparison. */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_GENERATE Start And Stop Generation + * @{ + */ +#define LL_I2C_GENERATE_NOSTARTSTOP 0x00000000U +/*!< Don't Generate Stop and Start condition. */ +#define LL_I2C_GENERATE_STOP (uint32_t)(0x80000000U | I2C_CR2_STOP) +/*!< Generate Stop condition (Size should be set to 0). */ +#define LL_I2C_GENERATE_START_READ (uint32_t)(0x80000000U | I2C_CR2_START | I2C_CR2_RD_WRN) +/*!< Generate Start for read request. */ +#define LL_I2C_GENERATE_START_WRITE (uint32_t)(0x80000000U | I2C_CR2_START) +/*!< Generate Start for write request. */ +#define LL_I2C_GENERATE_RESTART_7BIT_READ (uint32_t)(0x80000000U | I2C_CR2_START | I2C_CR2_RD_WRN) +/*!< Generate Restart for read request, slave 7Bit address. */ +#define LL_I2C_GENERATE_RESTART_7BIT_WRITE (uint32_t)(0x80000000U | I2C_CR2_START) +/*!< Generate Restart for write request, slave 7Bit address. */ +#define LL_I2C_GENERATE_RESTART_10BIT_READ (uint32_t)(0x80000000U | I2C_CR2_START | \ + I2C_CR2_RD_WRN | I2C_CR2_HEAD10R) +/*!< Generate Restart for read request, slave 10Bit address. */ +#define LL_I2C_GENERATE_RESTART_10BIT_WRITE (uint32_t)(0x80000000U | I2C_CR2_START) +/*!< Generate Restart for write request, slave 10Bit address.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_DIRECTION Read Write Direction + * @{ + */ +#define LL_I2C_DIRECTION_WRITE 0x00000000U /*!< Write transfer request by master, + slave enters receiver mode. */ +#define LL_I2C_DIRECTION_READ I2C_ISR_DIR /*!< Read transfer request by master, + slave enters transmitter mode.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_DMA_REG_DATA DMA Register Data + * @{ + */ +#define LL_I2C_DMA_REG_DATA_TRANSMIT 0x00000000U /*!< Get address of data register used for + transmission */ +#define LL_I2C_DMA_REG_DATA_RECEIVE 0x00000001U /*!< Get address of data register used for + reception */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_SMBUS_TIMEOUTA_MODE SMBus TimeoutA Mode SCL SDA Timeout + * @{ + */ +#define LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW 0x00000000U /*!< TimeoutA is used to detect + SCL low level timeout. */ +#define LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH I2C_TIMEOUTR_TIDLE /*!< TimeoutA is used to detect + both SCL and SDA high level timeout.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_SMBUS_TIMEOUT_SELECTION SMBus Timeout Selection + * @{ + */ +#define LL_I2C_SMBUS_TIMEOUTA I2C_TIMEOUTR_TIMOUTEN /*!< TimeoutA enable bit */ +#define LL_I2C_SMBUS_TIMEOUTB I2C_TIMEOUTR_TEXTEN /*!< TimeoutB (extended clock) + enable bit */ +#define LL_I2C_SMBUS_ALL_TIMEOUT (uint32_t)(I2C_TIMEOUTR_TIMOUTEN | \ + I2C_TIMEOUTR_TEXTEN) /*!< TimeoutA and TimeoutB +(extended clock) enable bits */ +/** + * @} + */ + +/** + * @} + */ + +/* 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_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_I2C_CONVERT_TIMINGS(__PRESCALER__, __SETUP_TIME__, __HOLD_TIME__, __SCLH_PERIOD__, __SCLL_PERIOD__) \ + ((((uint32_t)(__PRESCALER__) << I2C_TIMINGR_PRESC_Pos) & I2C_TIMINGR_PRESC) | \ + (((uint32_t)(__SETUP_TIME__) << I2C_TIMINGR_SCLDEL_Pos) & I2C_TIMINGR_SCLDEL) | \ + (((uint32_t)(__HOLD_TIME__) << I2C_TIMINGR_SDADEL_Pos) & I2C_TIMINGR_SDADEL) | \ + (((uint32_t)(__SCLH_PERIOD__) << I2C_TIMINGR_SCLH_Pos) & I2C_TIMINGR_SCLH) | \ + (((uint32_t)(__SCLL_PERIOD__) << I2C_TIMINGR_SCLL_Pos) & I2C_TIMINGR_SCLL)) +/** + * @} + */ + +/** + * @} + */ + +/* 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). + * @note When PE = 0, the I2C 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_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(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_PE) == (I2C_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 I2C is disabled (PE = 0). + * @rmtoll CR1 ANFOFF LL_I2C_ConfigFilters\n + * CR1 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*ti2cclk). + * 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]*ti2cclk. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ConfigFilters(I2C_TypeDef *I2Cx, uint32_t AnalogFilter, uint32_t DigitalFilter) +{ + MODIFY_REG(I2Cx->CR1, I2C_CR1_ANFOFF | I2C_CR1_DNF, AnalogFilter | (DigitalFilter << I2C_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 I2C is disabled (PE = 0). + * @rmtoll CR1 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*ti2cclk). + * 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]*ti2cclk. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetDigitalFilter(I2C_TypeDef *I2Cx, uint32_t DigitalFilter) +{ + MODIFY_REG(I2Cx->CR1, I2C_CR1_DNF, DigitalFilter << I2C_CR1_DNF_Pos); +} + +/** + * @brief Get the current Digital Noise Filter configuration. + * @rmtoll CR1 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(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR1, I2C_CR1_DNF) >> I2C_CR1_DNF_Pos); +} + +/** + * @brief Enable Analog Noise Filter. + * @note This filter can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll CR1 ANFOFF LL_I2C_EnableAnalogFilter + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableAnalogFilter(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ANFOFF); +} + +/** + * @brief Disable Analog Noise Filter. + * @note This filter can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll CR1 ANFOFF LL_I2C_DisableAnalogFilter + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableAnalogFilter(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ANFOFF); +} + +/** + * @brief Check if Analog Noise Filter is enabled or disabled. + * @rmtoll CR1 ANFOFF LL_I2C_IsEnabledAnalogFilter + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledAnalogFilter(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_ANFOFF) != (I2C_CR1_ANFOFF)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA transmission requests. + * @rmtoll CR1 TXDMAEN LL_I2C_EnableDMAReq_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableDMAReq_TX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_TXDMAEN); +} + +/** + * @brief Disable DMA transmission requests. + * @rmtoll CR1 TXDMAEN LL_I2C_DisableDMAReq_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableDMAReq_TX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_TXDMAEN); +} + +/** + * @brief Check if DMA transmission requests are enabled or disabled. + * @rmtoll CR1 TXDMAEN LL_I2C_IsEnabledDMAReq_TX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledDMAReq_TX(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_TXDMAEN) == (I2C_CR1_TXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA reception requests. + * @rmtoll CR1 RXDMAEN LL_I2C_EnableDMAReq_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableDMAReq_RX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_RXDMAEN); +} + +/** + * @brief Disable DMA reception requests. + * @rmtoll CR1 RXDMAEN LL_I2C_DisableDMAReq_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableDMAReq_RX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_RXDMAEN); +} + +/** + * @brief Check if DMA reception requests are enabled or disabled. + * @rmtoll CR1 RXDMAEN LL_I2C_IsEnabledDMAReq_RX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledDMAReq_RX(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_RXDMAEN) == (I2C_CR1_RXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll TXDR TXDATA LL_I2C_DMA_GetRegAddr\n + * RXDR RXDATA LL_I2C_DMA_GetRegAddr + * @param I2Cx I2C Instance + * @param Direction This parameter can be one of the following values: + * @arg @ref LL_I2C_DMA_REG_DATA_TRANSMIT + * @arg @ref LL_I2C_DMA_REG_DATA_RECEIVE + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_I2C_DMA_GetRegAddr(const I2C_TypeDef *I2Cx, uint32_t Direction) +{ + uint32_t data_reg_addr; + + if (Direction == LL_I2C_DMA_REG_DATA_TRANSMIT) + { + /* return address of TXDR register */ + data_reg_addr = (uint32_t) &(I2Cx->TXDR); + } + else + { + /* return address of RXDR register */ + data_reg_addr = (uint32_t) &(I2Cx->RXDR); + } + + return data_reg_addr; +} + +/** + * @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(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH) != (I2C_CR1_NOSTRETCH)) ? 1UL : 0UL); +} + +/** + * @brief Enable hardware byte control in slave mode. + * @rmtoll CR1 SBC LL_I2C_EnableSlaveByteControl + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSlaveByteControl(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_SBC); +} + +/** + * @brief Disable hardware byte control in slave mode. + * @rmtoll CR1 SBC LL_I2C_DisableSlaveByteControl + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSlaveByteControl(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_SBC); +} + +/** + * @brief Check if hardware byte control in slave mode is enabled or disabled. + * @rmtoll CR1 SBC LL_I2C_IsEnabledSlaveByteControl + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSlaveByteControl(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_SBC) == (I2C_CR1_SBC)) ? 1UL : 0UL); +} + +/** + * @brief Enable Wakeup from STOP. + * @note The macro IS_I2C_WAKEUP_FROMSTOP_INSTANCE(I2Cx) can be used to check whether or not + * WakeUpFromStop feature is supported by the I2Cx Instance. + * @note This bit can only be programmed when Digital Filter is disabled. + * @rmtoll CR1 WUPEN LL_I2C_EnableWakeUpFromStop + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableWakeUpFromStop(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_WUPEN); +} + +/** + * @brief Disable Wakeup from STOP. + * @note The macro IS_I2C_WAKEUP_FROMSTOP_INSTANCE(I2Cx) can be used to check whether or not + * WakeUpFromStop feature is supported by the I2Cx Instance. + * @rmtoll CR1 WUPEN LL_I2C_DisableWakeUpFromStop + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableWakeUpFromStop(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_WUPEN); +} + +/** + * @brief Check if Wakeup from STOP is enabled or disabled. + * @note The macro IS_I2C_WAKEUP_FROMSTOP_INSTANCE(I2Cx) can be used to check whether or not + * WakeUpFromStop feature is supported by the I2Cx Instance. + * @rmtoll CR1 WUPEN LL_I2C_IsEnabledWakeUpFromStop + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledWakeUpFromStop(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_WUPEN) == (I2C_CR1_WUPEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable General Call. + * @note When enabled the Address 0x00 is ACKed. + * @rmtoll CR1 GCEN LL_I2C_EnableGeneralCall + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableGeneralCall(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_GCEN); +} + +/** + * @brief Disable General Call. + * @note When disabled the Address 0x00 is NACKed. + * @rmtoll CR1 GCEN LL_I2C_DisableGeneralCall + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableGeneralCall(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_GCEN); +} + +/** + * @brief Check if General Call is enabled or disabled. + * @rmtoll CR1 GCEN LL_I2C_IsEnabledGeneralCall + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledGeneralCall(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_GCEN) == (I2C_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_I2C_SetMasterAddressingMode + * @param I2Cx I2C Instance. + * @param AddressingMode This parameter can be one of the following values: + * @arg @ref LL_I2C_ADDRESSING_MODE_7BIT + * @arg @ref LL_I2C_ADDRESSING_MODE_10BIT + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetMasterAddressingMode(I2C_TypeDef *I2Cx, uint32_t AddressingMode) +{ + MODIFY_REG(I2Cx->CR2, I2C_CR2_ADD10, AddressingMode); +} + +/** + * @brief Get the Master addressing mode. + * @rmtoll CR2 ADD10 LL_I2C_GetMasterAddressingMode + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_ADDRESSING_MODE_7BIT + * @arg @ref LL_I2C_ADDRESSING_MODE_10BIT + */ +__STATIC_INLINE uint32_t LL_I2C_GetMasterAddressingMode(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_ADD10)); +} + +/** + * @brief Set the Own Address1. + * @rmtoll OAR1 OA1 LL_I2C_SetOwnAddress1\n + * OAR1 OA1MODE 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_OA1 | I2C_OAR1_OA1MODE, OwnAddress1 | OwnAddrSize); +} + +/** + * @brief Enable acknowledge on Own Address1 match address. + * @rmtoll OAR1 OA1EN LL_I2C_EnableOwnAddress1 + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableOwnAddress1(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->OAR1, I2C_OAR1_OA1EN); +} + +/** + * @brief Disable acknowledge on Own Address1 match address. + * @rmtoll OAR1 OA1EN LL_I2C_DisableOwnAddress1 + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableOwnAddress1(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->OAR1, I2C_OAR1_OA1EN); +} + +/** + * @brief Check if Own Address1 acknowledge is enabled or disabled. + * @rmtoll OAR1 OA1EN LL_I2C_IsEnabledOwnAddress1 + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledOwnAddress1(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->OAR1, I2C_OAR1_OA1EN) == (I2C_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_I2C_SetOwnAddress2\n + * OAR2 OA2MSK LL_I2C_SetOwnAddress2 + * @param I2Cx I2C 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_I2C_OWNADDRESS2_NOMASK + * @arg @ref LL_I2C_OWNADDRESS2_MASK01 + * @arg @ref LL_I2C_OWNADDRESS2_MASK02 + * @arg @ref LL_I2C_OWNADDRESS2_MASK03 + * @arg @ref LL_I2C_OWNADDRESS2_MASK04 + * @arg @ref LL_I2C_OWNADDRESS2_MASK05 + * @arg @ref LL_I2C_OWNADDRESS2_MASK06 + * @arg @ref LL_I2C_OWNADDRESS2_MASK07 + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetOwnAddress2(I2C_TypeDef *I2Cx, uint32_t OwnAddress2, uint32_t OwnAddrMask) +{ + MODIFY_REG(I2Cx->OAR2, I2C_OAR2_OA2 | I2C_OAR2_OA2MSK, OwnAddress2 | OwnAddrMask); +} + +/** + * @brief Enable acknowledge on Own Address2 match address. + * @rmtoll OAR2 OA2EN LL_I2C_EnableOwnAddress2 + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableOwnAddress2(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->OAR2, I2C_OAR2_OA2EN); +} + +/** + * @brief Disable acknowledge on Own Address2 match address. + * @rmtoll OAR2 OA2EN LL_I2C_DisableOwnAddress2 + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableOwnAddress2(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->OAR2, I2C_OAR2_OA2EN); +} + +/** + * @brief Check if Own Address1 acknowledge is enabled or disabled. + * @rmtoll OAR2 OA2EN LL_I2C_IsEnabledOwnAddress2 + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledOwnAddress2(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->OAR2, I2C_OAR2_OA2EN) == (I2C_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 I2C is disabled (PE = 0). + * @rmtoll TIMINGR TIMINGR LL_I2C_SetTiming + * @param I2Cx I2C 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_I2C_SetTiming(I2C_TypeDef *I2Cx, uint32_t Timing) +{ + WRITE_REG(I2Cx->TIMINGR, Timing); +} + +/** + * @brief Get the Timing Prescaler setting. + * @rmtoll TIMINGR PRESC LL_I2C_GetTimingPrescaler + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_I2C_GetTimingPrescaler(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_PRESC) >> I2C_TIMINGR_PRESC_Pos); +} + +/** + * @brief Get the SCL low period setting. + * @rmtoll TIMINGR SCLL LL_I2C_GetClockLowPeriod + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetClockLowPeriod(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SCLL) >> I2C_TIMINGR_SCLL_Pos); +} + +/** + * @brief Get the SCL high period setting. + * @rmtoll TIMINGR SCLH LL_I2C_GetClockHighPeriod + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetClockHighPeriod(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SCLH) >> I2C_TIMINGR_SCLH_Pos); +} + +/** + * @brief Get the SDA hold time. + * @rmtoll TIMINGR SDADEL LL_I2C_GetDataHoldTime + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_I2C_GetDataHoldTime(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SDADEL) >> I2C_TIMINGR_SDADEL_Pos); +} + +/** + * @brief Get the SDA setup time. + * @rmtoll TIMINGR SCLDEL LL_I2C_GetDataSetupTime + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_I2C_GetDataSetupTime(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMINGR, I2C_TIMINGR_SCLDEL) >> I2C_TIMINGR_SCLDEL_Pos); +} + +/** + * @brief Configure peripheral mode. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 SMBHEN LL_I2C_SetMode\n + * CR1 SMBDEN 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_SMBHEN | I2C_CR1_SMBDEN, PeripheralMode); +} + +/** + * @brief Get peripheral mode. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 SMBHEN LL_I2C_GetMode\n + * CR1 SMBDEN 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(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR1, I2C_CR1_SMBHEN | I2C_CR1_SMBDEN)); +} + +/** + * @brief Enable SMBus alert (Host or Device mode) + * @note The macro 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 ALERTEN LL_I2C_EnableSMBusAlert + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusAlert(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ALERTEN); +} + +/** + * @brief Disable SMBus alert (Host or Device mode) + * @note The macro 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 ALERTEN LL_I2C_DisableSMBusAlert + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSMBusAlert(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ALERTEN); +} + +/** + * @brief Check if SMBus alert (Host or Device mode) is enabled or disabled. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 ALERTEN LL_I2C_IsEnabledSMBusAlert + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusAlert(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_ALERTEN) == (I2C_CR1_ALERTEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable SMBus Packet Error Calculation (PEC). + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 PECEN LL_I2C_EnableSMBusPEC + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusPEC(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_PECEN); +} + +/** + * @brief Disable SMBus Packet Error Calculation (PEC). + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 PECEN LL_I2C_DisableSMBusPEC + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSMBusPEC(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_PECEN); +} + +/** + * @brief Check if SMBus Packet Error Calculation (PEC) is enabled or disabled. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 PECEN LL_I2C_IsEnabledSMBusPEC + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPEC(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_PECEN) == (I2C_CR1_PECEN)) ? 1UL : 0UL); +} + +/** + * @brief Configure the SMBus Clock Timeout. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note This configuration can only be programmed when associated Timeout is disabled (TimeoutA and/orTimeoutB). + * @rmtoll TIMEOUTR TIMEOUTA LL_I2C_ConfigSMBusTimeout\n + * TIMEOUTR TIDLE LL_I2C_ConfigSMBusTimeout\n + * TIMEOUTR TIMEOUTB LL_I2C_ConfigSMBusTimeout + * @param I2Cx I2C 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_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW + * @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH + * @param TimeoutB + * @retval None + */ +__STATIC_INLINE void LL_I2C_ConfigSMBusTimeout(I2C_TypeDef *I2Cx, uint32_t TimeoutA, uint32_t TimeoutAMode, + uint32_t TimeoutB) +{ + MODIFY_REG(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIMEOUTA | I2C_TIMEOUTR_TIDLE | I2C_TIMEOUTR_TIMEOUTB, + TimeoutA | TimeoutAMode | (TimeoutB << I2C_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_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note These bits can only be programmed when TimeoutA is disabled. + * @rmtoll TIMEOUTR TIMEOUTA LL_I2C_SetSMBusTimeoutA + * @param I2Cx I2C Instance. + * @param TimeoutA This parameter must be a value between Min_Data=0 and Max_Data=0xFFF. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetSMBusTimeoutA(I2C_TypeDef *I2Cx, uint32_t TimeoutA) +{ + WRITE_REG(I2Cx->TIMEOUTR, TimeoutA); +} + +/** + * @brief Get the SMBus Clock TimeoutA setting. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll TIMEOUTR TIMEOUTA LL_I2C_GetSMBusTimeoutA + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetSMBusTimeoutA(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIMEOUTA)); +} + +/** + * @brief Set the SMBus Clock TimeoutA mode. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note This bit can only be programmed when TimeoutA is disabled. + * @rmtoll TIMEOUTR TIDLE LL_I2C_SetSMBusTimeoutAMode + * @param I2Cx I2C Instance. + * @param TimeoutAMode This parameter can be one of the following values: + * @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW + * @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetSMBusTimeoutAMode(I2C_TypeDef *I2Cx, uint32_t TimeoutAMode) +{ + WRITE_REG(I2Cx->TIMEOUTR, TimeoutAMode); +} + +/** + * @brief Get the SMBus Clock TimeoutA mode. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll TIMEOUTR TIDLE LL_I2C_GetSMBusTimeoutAMode + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SCL_LOW + * @arg @ref LL_I2C_SMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH + */ +__STATIC_INLINE uint32_t LL_I2C_GetSMBusTimeoutAMode(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIDLE)); +} + +/** + * @brief Configure the SMBus Extended Cumulative Clock TimeoutB (Master or Slave mode). + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note These bits can only be programmed when TimeoutB is disabled. + * @rmtoll TIMEOUTR TIMEOUTB LL_I2C_SetSMBusTimeoutB + * @param I2Cx I2C Instance. + * @param TimeoutB This parameter must be a value between Min_Data=0 and Max_Data=0xFFF. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetSMBusTimeoutB(I2C_TypeDef *I2Cx, uint32_t TimeoutB) +{ + WRITE_REG(I2Cx->TIMEOUTR, TimeoutB << I2C_TIMEOUTR_TIMEOUTB_Pos); +} + +/** + * @brief Get the SMBus Extended Cumulative Clock TimeoutB setting. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll TIMEOUTR TIMEOUTB LL_I2C_GetSMBusTimeoutB + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetSMBusTimeoutB(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TIMEOUTR, I2C_TIMEOUTR_TIMEOUTB) >> I2C_TIMEOUTR_TIMEOUTB_Pos); +} + +/** + * @brief Enable the SMBus Clock Timeout. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll TIMEOUTR TIMOUTEN LL_I2C_EnableSMBusTimeout\n + * TIMEOUTR TEXTEN LL_I2C_EnableSMBusTimeout + * @param I2Cx I2C Instance. + * @param ClockTimeout This parameter can be one of the following values: + * @arg @ref LL_I2C_SMBUS_TIMEOUTA + * @arg @ref LL_I2C_SMBUS_TIMEOUTB + * @arg @ref LL_I2C_SMBUS_ALL_TIMEOUT + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusTimeout(I2C_TypeDef *I2Cx, uint32_t ClockTimeout) +{ + SET_BIT(I2Cx->TIMEOUTR, ClockTimeout); +} + +/** + * @brief Disable the SMBus Clock Timeout. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll TIMEOUTR TIMOUTEN LL_I2C_DisableSMBusTimeout\n + * TIMEOUTR TEXTEN LL_I2C_DisableSMBusTimeout + * @param I2Cx I2C Instance. + * @param ClockTimeout This parameter can be one of the following values: + * @arg @ref LL_I2C_SMBUS_TIMEOUTA + * @arg @ref LL_I2C_SMBUS_TIMEOUTB + * @arg @ref LL_I2C_SMBUS_ALL_TIMEOUT + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSMBusTimeout(I2C_TypeDef *I2Cx, uint32_t ClockTimeout) +{ + CLEAR_BIT(I2Cx->TIMEOUTR, ClockTimeout); +} + +/** + * @brief Check if the SMBus Clock Timeout is enabled or disabled. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll TIMEOUTR TIMOUTEN LL_I2C_IsEnabledSMBusTimeout\n + * TIMEOUTR TEXTEN LL_I2C_IsEnabledSMBusTimeout + * @param I2Cx I2C Instance. + * @param ClockTimeout This parameter can be one of the following values: + * @arg @ref LL_I2C_SMBUS_TIMEOUTA + * @arg @ref LL_I2C_SMBUS_TIMEOUTB + * @arg @ref LL_I2C_SMBUS_ALL_TIMEOUT + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusTimeout(const I2C_TypeDef *I2Cx, uint32_t ClockTimeout) +{ + return ((READ_BIT(I2Cx->TIMEOUTR, (I2C_TIMEOUTR_TIMOUTEN | I2C_TIMEOUTR_TEXTEN)) == \ + (ClockTimeout)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup I2C_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable TXIS interrupt. + * @rmtoll CR1 TXIE LL_I2C_EnableIT_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_TX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_TXIE); +} + +/** + * @brief Disable TXIS interrupt. + * @rmtoll CR1 TXIE LL_I2C_DisableIT_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_TX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_TXIE); +} + +/** + * @brief Check if the TXIS Interrupt is enabled or disabled. + * @rmtoll CR1 TXIE LL_I2C_IsEnabledIT_TX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_TX(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_TXIE) == (I2C_CR1_TXIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable RXNE interrupt. + * @rmtoll CR1 RXIE LL_I2C_EnableIT_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_RX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_RXIE); +} + +/** + * @brief Disable RXNE interrupt. + * @rmtoll CR1 RXIE LL_I2C_DisableIT_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_RX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_RXIE); +} + +/** + * @brief Check if the RXNE Interrupt is enabled or disabled. + * @rmtoll CR1 RXIE LL_I2C_IsEnabledIT_RX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_RX(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_RXIE) == (I2C_CR1_RXIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Address match interrupt (slave mode only). + * @rmtoll CR1 ADDRIE LL_I2C_EnableIT_ADDR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_ADDR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ADDRIE); +} + +/** + * @brief Disable Address match interrupt (slave mode only). + * @rmtoll CR1 ADDRIE LL_I2C_DisableIT_ADDR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_ADDR(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ADDRIE); +} + +/** + * @brief Check if Address match interrupt is enabled or disabled. + * @rmtoll CR1 ADDRIE LL_I2C_IsEnabledIT_ADDR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_ADDR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_ADDRIE) == (I2C_CR1_ADDRIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Not acknowledge received interrupt. + * @rmtoll CR1 NACKIE LL_I2C_EnableIT_NACK + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_NACK(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_NACKIE); +} + +/** + * @brief Disable Not acknowledge received interrupt. + * @rmtoll CR1 NACKIE LL_I2C_DisableIT_NACK + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_NACK(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_NACKIE); +} + +/** + * @brief Check if Not acknowledge received interrupt is enabled or disabled. + * @rmtoll CR1 NACKIE LL_I2C_IsEnabledIT_NACK + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_NACK(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_NACKIE) == (I2C_CR1_NACKIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable STOP detection interrupt. + * @rmtoll CR1 STOPIE LL_I2C_EnableIT_STOP + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_STOP(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_STOPIE); +} + +/** + * @brief Disable STOP detection interrupt. + * @rmtoll CR1 STOPIE LL_I2C_DisableIT_STOP + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_STOP(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_STOPIE); +} + +/** + * @brief Check if STOP detection interrupt is enabled or disabled. + * @rmtoll CR1 STOPIE LL_I2C_IsEnabledIT_STOP + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_STOP(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_STOPIE) == (I2C_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_I2C_EnableIT_TC + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_TC(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_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_I2C_DisableIT_TC + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_TC(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_TCIE); +} + +/** + * @brief Check if Transfer Complete interrupt is enabled or disabled. + * @rmtoll CR1 TCIE LL_I2C_IsEnabledIT_TC + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_TC(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_TCIE) == (I2C_CR1_TCIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Error interrupts. + * @note The macro 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 : + * 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_I2C_EnableIT_ERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_ERR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ERRIE); +} + +/** + * @brief Disable Error interrupts. + * @note The macro 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 : + * 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_I2C_DisableIT_ERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_ERR(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ERRIE); +} + +/** + * @brief Check if Error interrupts are enabled or disabled. + * @rmtoll CR1 ERRIE LL_I2C_IsEnabledIT_ERR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_ERR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR1, I2C_CR1_ERRIE) == (I2C_CR1_ERRIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @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 ISR TXE LL_I2C_IsActiveFlag_TXE + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TXE(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_TXE) == (I2C_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_I2C_IsActiveFlag_TXIS + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TXIS(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_TXIS) == (I2C_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_I2C_IsActiveFlag_RXNE + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_RXNE(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_RXNE) == (I2C_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_I2C_IsActiveFlag_ADDR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ADDR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_ADDR) == (I2C_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_I2C_IsActiveFlag_NACK + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_NACK(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_NACKF) == (I2C_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_I2C_IsActiveFlag_STOP + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_STOP(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_STOPF) == (I2C_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_I2C_IsActiveFlag_TC + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TC(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_TC) == (I2C_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_I2C_IsActiveFlag_TCR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TCR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_TCR) == (I2C_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_I2C_IsActiveFlag_BERR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BERR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_BERR) == (I2C_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_I2C_IsActiveFlag_ARLO + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ARLO(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_ARLO) == (I2C_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_I2C_IsActiveFlag_OVR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_OVR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_OVR) == (I2C_ISR_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of SMBus PEC error flag in reception. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note RESET: Clear default value. + * SET: When the received PEC does not match with the PEC register content. + * @rmtoll ISR PECERR LL_I2C_IsActiveSMBusFlag_PECERR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_PECERR(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_PECERR) == (I2C_ISR_PECERR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of SMBus Timeout detection flag. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note RESET: Clear default value. + * SET: When a timeout or extended clock timeout occurs. + * @rmtoll ISR TIMEOUT LL_I2C_IsActiveSMBusFlag_TIMEOUT + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_TIMEOUT(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_TIMEOUT) == (I2C_ISR_TIMEOUT)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of SMBus alert flag. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note RESET: Clear default value. + * SET: When SMBus host configuration, SMBus alert enabled and + * a falling edge event occurs on SMBA pin. + * @rmtoll ISR ALERT LL_I2C_IsActiveSMBusFlag_ALERT + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_ALERT(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_ALERT) == (I2C_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_I2C_IsActiveFlag_BUSY + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BUSY(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->ISR, I2C_ISR_BUSY) == (I2C_ISR_BUSY)) ? 1UL : 0UL); +} + +/** + * @brief Clear Address Matched flag. + * @rmtoll ICR ADDRCF LL_I2C_ClearFlag_ADDR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_ADDR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_ADDRCF); +} + +/** + * @brief Clear Not Acknowledge flag. + * @rmtoll ICR NACKCF LL_I2C_ClearFlag_NACK + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_NACK(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_NACKCF); +} + +/** + * @brief Clear Stop detection flag. + * @rmtoll ICR STOPCF LL_I2C_ClearFlag_STOP + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_STOP(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_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_I2C_ClearFlag_TXE + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_TXE(I2C_TypeDef *I2Cx) +{ + WRITE_REG(I2Cx->ISR, I2C_ISR_TXE); +} + +/** + * @brief Clear Bus error flag. + * @rmtoll ICR BERRCF LL_I2C_ClearFlag_BERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_BERR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_BERRCF); +} + +/** + * @brief Clear Arbitration lost flag. + * @rmtoll ICR ARLOCF LL_I2C_ClearFlag_ARLO + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_ARLO(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_ARLOCF); +} + +/** + * @brief Clear Overrun/Underrun flag. + * @rmtoll ICR OVRCF LL_I2C_ClearFlag_OVR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_OVR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_OVRCF); +} + +/** + * @brief Clear SMBus PEC error flag. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll ICR PECCF LL_I2C_ClearSMBusFlag_PECERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearSMBusFlag_PECERR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_PECCF); +} + +/** + * @brief Clear SMBus Timeout detection flag. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll ICR TIMOUTCF LL_I2C_ClearSMBusFlag_TIMEOUT + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearSMBusFlag_TIMEOUT(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_TIMOUTCF); +} + +/** + * @brief Clear SMBus Alert flag. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll ICR ALERTCF LL_I2C_ClearSMBusFlag_ALERT + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearSMBusFlag_ALERT(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->ICR, I2C_ICR_ALERTCF); +} + +/** + * @} + */ + +/** @defgroup I2C_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_I2C_EnableAutoEndMode + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableAutoEndMode(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_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_I2C_DisableAutoEndMode + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableAutoEndMode(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_AUTOEND); +} + +/** + * @brief Check if automatic STOP condition is enabled or disabled. + * @rmtoll CR2 AUTOEND LL_I2C_IsEnabledAutoEndMode + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledAutoEndMode(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR2, I2C_CR2_AUTOEND) == (I2C_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_I2C_EnableReloadMode + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableReloadMode(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_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_I2C_DisableReloadMode + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableReloadMode(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_RELOAD); +} + +/** + * @brief Check if reload mode is enabled or disabled. + * @rmtoll CR2 RELOAD LL_I2C_IsEnabledReloadMode + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledReloadMode(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR2, I2C_CR2_RELOAD) == (I2C_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_I2C_SetTransferSize + * @param I2Cx I2C Instance. + * @param TransferSize This parameter must be a value between Min_Data=0x00 and Max_Data=0xFF. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetTransferSize(I2C_TypeDef *I2Cx, uint32_t TransferSize) +{ + MODIFY_REG(I2Cx->CR2, I2C_CR2_NBYTES, TransferSize << I2C_CR2_NBYTES_Pos); +} + +/** + * @brief Get the number of bytes configured for transfer. + * @rmtoll CR2 NBYTES LL_I2C_GetTransferSize + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetTransferSize(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_NBYTES) >> I2C_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_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->CR2, I2C_CR2_NACK, 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 CR2 START LL_I2C_GenerateStartCondition + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_GenerateStartCondition(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_START); +} + +/** + * @brief Generate a STOP condition after the current byte transfer (master mode). + * @rmtoll CR2 STOP LL_I2C_GenerateStopCondition + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_GenerateStopCondition(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_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_I2C_EnableAuto10BitRead + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableAuto10BitRead(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_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_I2C_DisableAuto10BitRead + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableAuto10BitRead(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_HEAD10R); +} + +/** + * @brief Check if automatic RESTART Read request condition for 10bit address header is enabled or disabled. + * @rmtoll CR2 HEAD10R LL_I2C_IsEnabledAuto10BitRead + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledAuto10BitRead(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR2, I2C_CR2_HEAD10R) != (I2C_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_I2C_SetTransferRequest + * @param I2Cx I2C Instance. + * @param TransferRequest This parameter can be one of the following values: + * @arg @ref LL_I2C_REQUEST_WRITE + * @arg @ref LL_I2C_REQUEST_READ + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetTransferRequest(I2C_TypeDef *I2Cx, uint32_t TransferRequest) +{ + MODIFY_REG(I2Cx->CR2, I2C_CR2_RD_WRN, TransferRequest); +} + +/** + * @brief Get the transfer direction requested (master mode). + * @rmtoll CR2 RD_WRN LL_I2C_GetTransferRequest + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_REQUEST_WRITE + * @arg @ref LL_I2C_REQUEST_READ + */ +__STATIC_INLINE uint32_t LL_I2C_GetTransferRequest(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_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_I2C_SetSlaveAddr + * @param I2Cx I2C Instance. + * @param SlaveAddr This parameter must be a value between Min_Data=0x00 and Max_Data=0x3F. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetSlaveAddr(I2C_TypeDef *I2Cx, uint32_t SlaveAddr) +{ + MODIFY_REG(I2Cx->CR2, I2C_CR2_SADD, SlaveAddr); +} + +/** + * @brief Get the slave address programmed for transfer. + * @rmtoll CR2 SADD LL_I2C_GetSlaveAddr + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0x3F + */ +__STATIC_INLINE uint32_t LL_I2C_GetSlaveAddr(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR2, I2C_CR2_SADD)); +} + +/** + * @brief Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set). + * @rmtoll CR2 SADD LL_I2C_HandleTransfer\n + * CR2 ADD10 LL_I2C_HandleTransfer\n + * CR2 RD_WRN LL_I2C_HandleTransfer\n + * CR2 START LL_I2C_HandleTransfer\n + * CR2 STOP LL_I2C_HandleTransfer\n + * CR2 RELOAD LL_I2C_HandleTransfer\n + * CR2 NBYTES LL_I2C_HandleTransfer\n + * CR2 AUTOEND LL_I2C_HandleTransfer\n + * CR2 HEAD10R LL_I2C_HandleTransfer + * @param I2Cx I2C Instance. + * @param SlaveAddr Specifies the slave address to be programmed. + * @param SlaveAddrSize This parameter can be one of the following values: + * @arg @ref LL_I2C_ADDRSLAVE_7BIT + * @arg @ref LL_I2C_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_I2C_MODE_RELOAD + * @arg @ref LL_I2C_MODE_AUTOEND + * @arg @ref LL_I2C_MODE_SOFTEND + * @arg @ref LL_I2C_MODE_SMBUS_RELOAD + * @arg @ref LL_I2C_MODE_SMBUS_AUTOEND_NO_PEC + * @arg @ref LL_I2C_MODE_SMBUS_SOFTEND_NO_PEC + * @arg @ref LL_I2C_MODE_SMBUS_AUTOEND_WITH_PEC + * @arg @ref LL_I2C_MODE_SMBUS_SOFTEND_WITH_PEC + * @param Request This parameter can be one of the following values: + * @arg @ref LL_I2C_GENERATE_NOSTARTSTOP + * @arg @ref LL_I2C_GENERATE_STOP + * @arg @ref LL_I2C_GENERATE_START_READ + * @arg @ref LL_I2C_GENERATE_START_WRITE + * @arg @ref LL_I2C_GENERATE_RESTART_7BIT_READ + * @arg @ref LL_I2C_GENERATE_RESTART_7BIT_WRITE + * @arg @ref LL_I2C_GENERATE_RESTART_10BIT_READ + * @arg @ref LL_I2C_GENERATE_RESTART_10BIT_WRITE + * @retval None + */ +__STATIC_INLINE void LL_I2C_HandleTransfer(I2C_TypeDef *I2Cx, uint32_t SlaveAddr, uint32_t SlaveAddrSize, + uint32_t TransferSize, uint32_t EndMode, uint32_t Request) +{ + MODIFY_REG(I2Cx->CR2, I2C_CR2_SADD | I2C_CR2_ADD10 | + (I2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - I2C_CR2_RD_WRN_Pos))) | + I2C_CR2_START | I2C_CR2_STOP | I2C_CR2_RELOAD | + I2C_CR2_NBYTES | I2C_CR2_AUTOEND | I2C_CR2_HEAD10R, + SlaveAddr | SlaveAddrSize | (TransferSize << I2C_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_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(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->ISR, I2C_ISR_DIR)); +} + +/** + * @brief Return the slave matched address. + * @rmtoll ISR ADDCODE LL_I2C_GetAddressMatchCode + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0x3F + */ +__STATIC_INLINE uint32_t LL_I2C_GetAddressMatchCode(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->ISR, I2C_ISR_ADDCODE) >> I2C_ISR_ADDCODE_Pos << 1); +} + +/** + * @brief Enable internal comparison of the SMBus Packet Error byte (transmission or reception mode). + * @note The macro 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 when a STOP condition + or an Address Matched is received. + * This bit has no effect when RELOAD bit is set. + * This bit has no effect in device mode when SBC bit is not set. + * @rmtoll CR2 PECBYTE LL_I2C_EnableSMBusPECCompare + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusPECCompare(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_PECBYTE); +} + +/** + * @brief Check if the SMBus Packet Error byte internal comparison is requested or not. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR2 PECBYTE LL_I2C_IsEnabledSMBusPECCompare + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPECCompare(const I2C_TypeDef *I2Cx) +{ + return ((READ_BIT(I2Cx->CR2, I2C_CR2_PECBYTE) == (I2C_CR2_PECBYTE)) ? 1UL : 0UL); +} + +/** + * @brief Get the SMBus Packet Error byte calculated. + * @note The macro IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll PECR PEC LL_I2C_GetSMBusPEC + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetSMBusPEC(const I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->PECR, I2C_PECR_PEC)); +} + +/** + * @brief Read Receive Data register. + * @rmtoll RXDR RXDATA LL_I2C_ReceiveData8 + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_I2C_ReceiveData8(const I2C_TypeDef *I2Cx) +{ + return (uint8_t)(READ_BIT(I2Cx->RXDR, I2C_RXDR_RXDATA)); +} + +/** + * @brief Write in Transmit Data Register . + * @rmtoll TXDR TXDATA LL_I2C_TransmitData8 + * @param I2Cx I2C Instance. + * @param Data Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_I2C_TransmitData8(I2C_TypeDef *I2Cx, uint8_t Data) +{ + WRITE_REG(I2Cx->TXDR, Data); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2C_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_I2C_Init(I2C_TypeDef *I2Cx, const LL_I2C_InitTypeDef *I2C_InitStruct); +ErrorStatus LL_I2C_DeInit(const I2C_TypeDef *I2Cx); +void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct); + + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* I2C1 || I2C2 || I2C3 || I2C4 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_I2C_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_pwr.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_pwr.h new file mode 100644 index 0000000..4660f30 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_pwr.h @@ -0,0 +1,1675 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_pwr.h + * @author MCD Application Team + * @brief Header file of PWR 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 STM32L4xx_LL_PWR_H +#define STM32L4xx_LL_PWR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(PWR) + +/** @defgroup PWR_LL PWR + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup PWR_LL_Exported_Constants PWR Exported Constants + * @{ + */ + +/** @defgroup PWR_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_PWR_WriteReg function + * @{ + */ +#define LL_PWR_SCR_CSBF PWR_SCR_CSBF +#define LL_PWR_SCR_CWUF PWR_SCR_CWUF +#define LL_PWR_SCR_CWUF5 PWR_SCR_CWUF5 +#define LL_PWR_SCR_CWUF4 PWR_SCR_CWUF4 +#define LL_PWR_SCR_CWUF3 PWR_SCR_CWUF3 +#define LL_PWR_SCR_CWUF2 PWR_SCR_CWUF2 +#define LL_PWR_SCR_CWUF1 PWR_SCR_CWUF1 +/** + * @} + */ + +/** @defgroup PWR_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_PWR_ReadReg function + * @{ + */ +#define LL_PWR_SR1_WUFI PWR_SR1_WUFI +#if defined(PWR_SR1_EXT_SMPS_RDY) +#define LL_PWR_SR1_EXT_SMPS_RDY PWR_SR1_EXT_SMPS_RDY +#endif /* PWR_SR1_EXT_SMPS_RDY */ +#define LL_PWR_SR1_SBF PWR_SR1_SBF +#define LL_PWR_SR1_WUF5 PWR_SR1_WUF5 +#define LL_PWR_SR1_WUF4 PWR_SR1_WUF4 +#define LL_PWR_SR1_WUF3 PWR_SR1_WUF3 +#define LL_PWR_SR1_WUF2 PWR_SR1_WUF2 +#define LL_PWR_SR1_WUF1 PWR_SR1_WUF1 +#if defined(PWR_SR2_PVMO4) +#define LL_PWR_SR2_PVMO4 PWR_SR2_PVMO4 +#endif /* PWR_SR2_PVMO4 */ +#if defined(PWR_SR2_PVMO3) +#define LL_PWR_SR2_PVMO3 PWR_SR2_PVMO3 +#endif /* PWR_SR2_PVMO3 */ +#if defined(PWR_SR2_PVMO2) +#define LL_PWR_SR2_PVMO2 PWR_SR2_PVMO2 +#endif /* PWR_SR2_PVMO2 */ +#if defined(PWR_SR2_PVMO1) +#define LL_PWR_SR2_PVMO1 PWR_SR2_PVMO1 +#endif /* PWR_SR2_PVMO1 */ +#define LL_PWR_SR2_PVDO PWR_SR2_PVDO +#define LL_PWR_SR2_VOSF PWR_SR2_VOSF +#define LL_PWR_SR2_REGLPF PWR_SR2_REGLPF +#define LL_PWR_SR2_REGLPS PWR_SR2_REGLPS +/** + * @} + */ + +/** @defgroup PWR_LL_EC_REGU_VOLTAGE REGU VOLTAGE + * @{ + */ +#define LL_PWR_REGU_VOLTAGE_SCALE1 (PWR_CR1_VOS_0) +#define LL_PWR_REGU_VOLTAGE_SCALE2 (PWR_CR1_VOS_1) +/** + * @} + */ + +/** @defgroup PWR_LL_EC_MODE_PWR MODE PWR + * @{ + */ +#define LL_PWR_MODE_STOP0 (PWR_CR1_LPMS_STOP0) +#define LL_PWR_MODE_STOP1 (PWR_CR1_LPMS_STOP1) +#define LL_PWR_MODE_STOP2 (PWR_CR1_LPMS_STOP2) +#define LL_PWR_MODE_STANDBY (PWR_CR1_LPMS_STANDBY) +#define LL_PWR_MODE_SHUTDOWN (PWR_CR1_LPMS_SHUTDOWN) +/** + * @} + */ + +/** @defgroup PWR_LL_EC_PVM_VDDUSB_1 Peripheral voltage monitoring + * @{ + */ +#if defined(PWR_CR2_PVME1) +#define LL_PWR_PVM_VDDUSB_1_2V (PWR_CR2_PVME1) /* Monitoring VDDUSB vs. 1.2V */ +#endif +#if defined(PWR_CR2_PVME2) +#define LL_PWR_PVM_VDDIO2_0_9V (PWR_CR2_PVME2) /* Monitoring VDDIO2 vs. 0.9V */ +#endif +#if defined(PWR_CR2_PVME3) +#define LL_PWR_PVM_VDDA_1_62V (PWR_CR2_PVME3) /* Monitoring VDDA vs. 1.62V */ +#endif +#if defined(PWR_CR2_PVME4) +#define LL_PWR_PVM_VDDA_2_2V (PWR_CR2_PVME4) /* Monitoring VDDA vs. 2.2V */ +#endif +/** + * @} + */ + +/** @defgroup PWR_LL_EC_PVDLEVEL PVDLEVEL + * @{ + */ +#define LL_PWR_PVDLEVEL_0 (PWR_CR2_PLS_LEV0) /* VPVD0 around 2.0 V */ +#define LL_PWR_PVDLEVEL_1 (PWR_CR2_PLS_LEV1) /* VPVD1 around 2.2 V */ +#define LL_PWR_PVDLEVEL_2 (PWR_CR2_PLS_LEV2) /* VPVD2 around 2.4 V */ +#define LL_PWR_PVDLEVEL_3 (PWR_CR2_PLS_LEV3) /* VPVD3 around 2.5 V */ +#define LL_PWR_PVDLEVEL_4 (PWR_CR2_PLS_LEV4) /* VPVD4 around 2.6 V */ +#define LL_PWR_PVDLEVEL_5 (PWR_CR2_PLS_LEV5) /* VPVD5 around 2.8 V */ +#define LL_PWR_PVDLEVEL_6 (PWR_CR2_PLS_LEV6) /* VPVD6 around 2.9 V */ +#define LL_PWR_PVDLEVEL_7 (PWR_CR2_PLS_LEV7) /* External input analog voltage (Compare internally to VREFINT) */ +/** + * @} + */ + +/** @defgroup PWR_LL_EC_WAKEUP WAKEUP + * @{ + */ +#define LL_PWR_WAKEUP_PIN1 (PWR_CR3_EWUP1) +#define LL_PWR_WAKEUP_PIN2 (PWR_CR3_EWUP2) +#define LL_PWR_WAKEUP_PIN3 (PWR_CR3_EWUP3) +#define LL_PWR_WAKEUP_PIN4 (PWR_CR3_EWUP4) +#define LL_PWR_WAKEUP_PIN5 (PWR_CR3_EWUP5) +/** + * @} + */ + +/** @defgroup PWR_LL_EC_BATT_CHARG_RESISTOR BATT CHARG RESISTOR + * @{ + */ +#define LL_PWR_BATT_CHARG_RESISTOR_5K (0x00000000U) +#define LL_PWR_BATT_CHARGRESISTOR_1_5K (PWR_CR4_VBRS) +/** + * @} + */ + +/** @defgroup PWR_LL_EC_SRAM2_CONTENT_RETENTION SRAM2 CONTENT RETENTION + * @{ + */ +#define LL_PWR_NO_SRAM2_RETENTION (0x00000000U) +#if defined(PWR_CR3_RRS_1) +#define LL_PWR_FULL_SRAM2_RETENTION PWR_CR3_RRS_0 +#define LL_PWR_4KBYTES_SRAM2_RETENTION PWR_CR3_RRS_1 +#else +#define LL_PWR_FULL_SRAM2_RETENTION PWR_CR3_RRS +#endif /* PWR_CR3_RRS_1 */ +/** + * @} + */ + +/** @defgroup PWR_LL_EC_GPIO GPIO + * @{ + */ +#define LL_PWR_GPIO_A ((uint32_t)(&(PWR->PUCRA))) +#define LL_PWR_GPIO_B ((uint32_t)(&(PWR->PUCRB))) +#define LL_PWR_GPIO_C ((uint32_t)(&(PWR->PUCRC))) +#define LL_PWR_GPIO_D ((uint32_t)(&(PWR->PUCRD))) +#define LL_PWR_GPIO_E ((uint32_t)(&(PWR->PUCRE))) +#if defined(GPIOF) +#define LL_PWR_GPIO_F ((uint32_t)(&(PWR->PUCRF))) +#endif +#if defined(GPIOG) +#define LL_PWR_GPIO_G ((uint32_t)(&(PWR->PUCRG))) +#endif +#if defined(GPIOH) +#define LL_PWR_GPIO_H ((uint32_t)(&(PWR->PUCRH))) +#endif +#if defined(GPIOI) +#define LL_PWR_GPIO_I ((uint32_t)(&(PWR->PUCRI))) +#endif +/** + * @} + */ + +/** @defgroup PWR_LL_EC_GPIO_BIT GPIO BIT + * @{ + */ +#define LL_PWR_GPIO_BIT_0 (0x00000001U) +#define LL_PWR_GPIO_BIT_1 (0x00000002U) +#define LL_PWR_GPIO_BIT_2 (0x00000004U) +#define LL_PWR_GPIO_BIT_3 (0x00000008U) +#define LL_PWR_GPIO_BIT_4 (0x00000010U) +#define LL_PWR_GPIO_BIT_5 (0x00000020U) +#define LL_PWR_GPIO_BIT_6 (0x00000040U) +#define LL_PWR_GPIO_BIT_7 (0x00000080U) +#define LL_PWR_GPIO_BIT_8 (0x00000100U) +#define LL_PWR_GPIO_BIT_9 (0x00000200U) +#define LL_PWR_GPIO_BIT_10 (0x00000400U) +#define LL_PWR_GPIO_BIT_11 (0x00000800U) +#define LL_PWR_GPIO_BIT_12 (0x00001000U) +#define LL_PWR_GPIO_BIT_13 (0x00002000U) +#define LL_PWR_GPIO_BIT_14 (0x00004000U) +#define LL_PWR_GPIO_BIT_15 (0x00008000U) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup PWR_LL_Exported_Macros PWR Exported Macros + * @{ + */ + +/** @defgroup PWR_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in PWR register + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_PWR_WriteReg(__REG__, __VALUE__) WRITE_REG(PWR->__REG__, (__VALUE__)) + +/** + * @brief Read a value in PWR register + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_PWR_ReadReg(__REG__) READ_REG(PWR->__REG__) +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup PWR_LL_Exported_Functions PWR Exported Functions + * @{ + */ + +/** @defgroup PWR_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Switch the regulator from main mode to low-power mode + * @rmtoll CR1 LPR LL_PWR_EnableLowPowerRunMode + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableLowPowerRunMode(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_LPR); +} + +/** + * @brief Switch the regulator from low-power mode to main mode + * @rmtoll CR1 LPR LL_PWR_DisableLowPowerRunMode + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableLowPowerRunMode(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_LPR); +} + +/** + * @brief Switch from run main mode to run low-power mode. + * @rmtoll CR1 LPR LL_PWR_EnterLowPowerRunMode + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnterLowPowerRunMode(void) +{ + LL_PWR_EnableLowPowerRunMode(); +} + +/** + * @brief Switch from run main mode to low-power mode. + * @rmtoll CR1 LPR LL_PWR_ExitLowPowerRunMode + * @retval None + */ +__STATIC_INLINE void LL_PWR_ExitLowPowerRunMode(void) +{ + LL_PWR_DisableLowPowerRunMode(); +} + +/** + * @brief Check if the regulator is in low-power mode + * @rmtoll CR1 LPR LL_PWR_IsEnabledLowPowerRunMode + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledLowPowerRunMode(void) +{ + return ((READ_BIT(PWR->CR1, PWR_CR1_LPR) == (PWR_CR1_LPR)) ? 1UL : 0UL); +} + +/** + * @brief Set the main internal regulator output voltage + * @note This configuration may be completed with LL_PWR_EnableRange1BoostMode() on STM32L4Rx/STM32L4Sx devices. + * @rmtoll CR1 VOS LL_PWR_SetRegulVoltageScaling + * @param VoltageScaling This parameter can be one of the following values: + * @arg @ref LL_PWR_REGU_VOLTAGE_SCALE1 + * @arg @ref LL_PWR_REGU_VOLTAGE_SCALE2 + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetRegulVoltageScaling(uint32_t VoltageScaling) +{ + MODIFY_REG(PWR->CR1, PWR_CR1_VOS, VoltageScaling); +} + +/** + * @brief Get the main internal regulator output voltage + * @rmtoll CR1 VOS LL_PWR_GetRegulVoltageScaling + * @retval Returned value can be one of the following values: + * @arg @ref LL_PWR_REGU_VOLTAGE_SCALE1 + * @arg @ref LL_PWR_REGU_VOLTAGE_SCALE2 + */ +__STATIC_INLINE uint32_t LL_PWR_GetRegulVoltageScaling(void) +{ + return (uint32_t)(READ_BIT(PWR->CR1, PWR_CR1_VOS)); +} + +#if defined(PWR_CR5_R1MODE) +/** + * @brief Enable main regulator voltage range 1 boost mode + * @rmtoll CR5 R1MODE LL_PWR_EnableRange1BoostMode + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableRange1BoostMode(void) +{ + CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE); +} + +/** + * @brief Disable main regulator voltage range 1 boost mode + * @rmtoll CR5 R1MODE LL_PWR_DisableRange1BoostMode + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableRange1BoostMode(void) +{ + SET_BIT(PWR->CR5, PWR_CR5_R1MODE); +} + +/** + * @brief Check if the main regulator voltage range 1 boost mode is enabled + * @rmtoll CR5 R1MODE LL_PWR_IsEnabledRange1BoostMode + * @retval Inverted state of bit (0 or 1). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledRange1BoostMode(void) +{ + return ((READ_BIT(PWR->CR5, PWR_CR5_R1MODE) == 0x0U) ? 1UL : 0UL); +} +#endif /* PWR_CR5_R1MODE */ + +/** + * @brief Enable access to the backup domain + * @rmtoll CR1 DBP LL_PWR_EnableBkUpAccess + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableBkUpAccess(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_DBP); +} + +/** + * @brief Disable access to the backup domain + * @rmtoll CR1 DBP LL_PWR_DisableBkUpAccess + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableBkUpAccess(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_DBP); +} + +/** + * @brief Check if the backup domain is enabled + * @rmtoll CR1 DBP LL_PWR_IsEnabledBkUpAccess + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledBkUpAccess(void) +{ + return ((READ_BIT(PWR->CR1, PWR_CR1_DBP) == (PWR_CR1_DBP)) ? 1UL : 0UL); +} + +/** + * @brief Set Low-Power mode + * @rmtoll CR1 LPMS LL_PWR_SetPowerMode + * @param LowPowerMode This parameter can be one of the following values: + * @arg @ref LL_PWR_MODE_STOP0 + * @arg @ref LL_PWR_MODE_STOP1 + * @arg @ref LL_PWR_MODE_STOP2 + * @arg @ref LL_PWR_MODE_STANDBY + * @arg @ref LL_PWR_MODE_SHUTDOWN + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetPowerMode(uint32_t LowPowerMode) +{ + MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, LowPowerMode); +} + +/** + * @brief Get Low-Power mode + * @rmtoll CR1 LPMS LL_PWR_GetPowerMode + * @retval Returned value can be one of the following values: + * @arg @ref LL_PWR_MODE_STOP0 + * @arg @ref LL_PWR_MODE_STOP1 + * @arg @ref LL_PWR_MODE_STOP2 + * @arg @ref LL_PWR_MODE_STANDBY + * @arg @ref LL_PWR_MODE_SHUTDOWN + */ +__STATIC_INLINE uint32_t LL_PWR_GetPowerMode(void) +{ + return (uint32_t)(READ_BIT(PWR->CR1, PWR_CR1_LPMS)); +} + +#if defined(PWR_CR1_RRSTP) +/** + * @brief Enable SRAM3 content retention in Stop mode + * @rmtoll CR1 RRSTP LL_PWR_EnableSRAM3Retention + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableSRAM3Retention(void) +{ + SET_BIT(PWR->CR1, PWR_CR1_RRSTP); +} + +/** + * @brief Disable SRAM3 content retention in Stop mode + * @rmtoll CR1 RRSTP LL_PWR_DisableSRAM3Retention + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableSRAM3Retention(void) +{ + CLEAR_BIT(PWR->CR1, PWR_CR1_RRSTP); +} + +/** + * @brief Check if SRAM3 content retention in Stop mode is enabled + * @rmtoll CR1 RRSTP LL_PWR_IsEnabledSRAM3Retention + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledSRAM3Retention(void) +{ + return ((READ_BIT(PWR->CR1, PWR_CR1_RRSTP) == (PWR_CR1_RRSTP)) ? 1UL : 0UL); +} +#endif /* PWR_CR1_RRSTP */ + +#if defined(PWR_CR3_DSIPDEN) +/** + * @brief Enable pull-down activation on DSI pins + * @rmtoll CR3 DSIPDEN LL_PWR_EnableDSIPinsPDActivation + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableDSIPinsPDActivation(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} + +/** + * @brief Disable pull-down activation on DSI pins + * @rmtoll CR3 DSIPDEN LL_PWR_DisableDSIPinsPDActivation + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableDSIPinsPDActivation(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} + +/** + * @brief Check if pull-down activation on DSI pins is enabled + * @rmtoll CR3 DSIPDEN LL_PWR_IsEnabledDSIPinsPDActivation + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledDSIPinsPDActivation(void) +{ + return ((READ_BIT(PWR->CR3, PWR_CR3_DSIPDEN) == (PWR_CR3_DSIPDEN)) ? 1UL : 0UL); +} +#endif /* PWR_CR3_DSIPDEN */ + +#if defined(PWR_CR2_USV) +/** + * @brief Enable VDDUSB supply + * @rmtoll CR2 USV LL_PWR_EnableVddUSB + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableVddUSB(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_USV); +} + +/** + * @brief Disable VDDUSB supply + * @rmtoll CR2 USV LL_PWR_DisableVddUSB + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableVddUSB(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_USV); +} + +/** + * @brief Check if VDDUSB supply is enabled + * @rmtoll CR2 USV LL_PWR_IsEnabledVddUSB + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledVddUSB(void) +{ + return ((READ_BIT(PWR->CR2, PWR_CR2_USV) == (PWR_CR2_USV)) ? 1UL : 0UL); +} +#endif + +#if defined(PWR_CR2_IOSV) +/** + * @brief Enable VDDIO2 supply + * @rmtoll CR2 IOSV LL_PWR_EnableVddIO2 + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableVddIO2(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_IOSV); +} + +/** + * @brief Disable VDDIO2 supply + * @rmtoll CR2 IOSV LL_PWR_DisableVddIO2 + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableVddIO2(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_IOSV); +} + +/** + * @brief Check if VDDIO2 supply is enabled + * @rmtoll CR2 IOSV LL_PWR_IsEnabledVddIO2 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledVddIO2(void) +{ + return ((READ_BIT(PWR->CR2, PWR_CR2_IOSV) == (PWR_CR2_IOSV)) ? 1UL : 0UL); +} +#endif + +/** + * @brief Enable the Power Voltage Monitoring on a peripheral + * @rmtoll CR2 PVME1 LL_PWR_EnablePVM\n + * CR2 PVME2 LL_PWR_EnablePVM\n + * CR2 PVME3 LL_PWR_EnablePVM\n + * CR2 PVME4 LL_PWR_EnablePVM + * @param PeriphVoltage This parameter can be one of the following values: + * @arg @ref LL_PWR_PVM_VDDUSB_1_2V (*) + * @arg @ref LL_PWR_PVM_VDDIO2_0_9V (*) + * @arg @ref LL_PWR_PVM_VDDA_1_62V + * @arg @ref LL_PWR_PVM_VDDA_2_2V + * + * (*) value not defined in all devices + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnablePVM(uint32_t PeriphVoltage) +{ + SET_BIT(PWR->CR2, PeriphVoltage); +} + +/** + * @brief Disable the Power Voltage Monitoring on a peripheral + * @rmtoll CR2 PVME1 LL_PWR_DisablePVM\n + * CR2 PVME2 LL_PWR_DisablePVM\n + * CR2 PVME3 LL_PWR_DisablePVM\n + * CR2 PVME4 LL_PWR_DisablePVM + * @param PeriphVoltage This parameter can be one of the following values: + * @arg @ref LL_PWR_PVM_VDDUSB_1_2V (*) + * @arg @ref LL_PWR_PVM_VDDIO2_0_9V (*) + * @arg @ref LL_PWR_PVM_VDDA_1_62V + * @arg @ref LL_PWR_PVM_VDDA_2_2V + * + * (*) value not defined in all devices + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisablePVM(uint32_t PeriphVoltage) +{ + CLEAR_BIT(PWR->CR2, PeriphVoltage); +} + +/** + * @brief Check if Power Voltage Monitoring is enabled on a peripheral + * @rmtoll CR2 PVME1 LL_PWR_IsEnabledPVM\n + * CR2 PVME2 LL_PWR_IsEnabledPVM\n + * CR2 PVME3 LL_PWR_IsEnabledPVM\n + * CR2 PVME4 LL_PWR_IsEnabledPVM + * @param PeriphVoltage This parameter can be one of the following values: + * @arg @ref LL_PWR_PVM_VDDUSB_1_2V (*) + * @arg @ref LL_PWR_PVM_VDDIO2_0_9V (*) + * @arg @ref LL_PWR_PVM_VDDA_1_62V + * @arg @ref LL_PWR_PVM_VDDA_2_2V + * + * (*) value not defined in all devices + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledPVM(uint32_t PeriphVoltage) +{ + return ((READ_BIT(PWR->CR2, PeriphVoltage) == (PeriphVoltage)) ? 1UL : 0UL); +} + +/** + * @brief Configure the voltage threshold detected by the Power Voltage Detector + * @rmtoll CR2 PLS LL_PWR_SetPVDLevel + * @param PVDLevel This parameter can be one of the following values: + * @arg @ref LL_PWR_PVDLEVEL_0 + * @arg @ref LL_PWR_PVDLEVEL_1 + * @arg @ref LL_PWR_PVDLEVEL_2 + * @arg @ref LL_PWR_PVDLEVEL_3 + * @arg @ref LL_PWR_PVDLEVEL_4 + * @arg @ref LL_PWR_PVDLEVEL_5 + * @arg @ref LL_PWR_PVDLEVEL_6 + * @arg @ref LL_PWR_PVDLEVEL_7 + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetPVDLevel(uint32_t PVDLevel) +{ + MODIFY_REG(PWR->CR2, PWR_CR2_PLS, PVDLevel); +} + +/** + * @brief Get the voltage threshold detection + * @rmtoll CR2 PLS LL_PWR_GetPVDLevel + * @retval Returned value can be one of the following values: + * @arg @ref LL_PWR_PVDLEVEL_0 + * @arg @ref LL_PWR_PVDLEVEL_1 + * @arg @ref LL_PWR_PVDLEVEL_2 + * @arg @ref LL_PWR_PVDLEVEL_3 + * @arg @ref LL_PWR_PVDLEVEL_4 + * @arg @ref LL_PWR_PVDLEVEL_5 + * @arg @ref LL_PWR_PVDLEVEL_6 + * @arg @ref LL_PWR_PVDLEVEL_7 + */ +__STATIC_INLINE uint32_t LL_PWR_GetPVDLevel(void) +{ + return (uint32_t)(READ_BIT(PWR->CR2, PWR_CR2_PLS)); +} + +/** + * @brief Enable Power Voltage Detector + * @rmtoll CR2 PVDE LL_PWR_EnablePVD + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnablePVD(void) +{ + SET_BIT(PWR->CR2, PWR_CR2_PVDE); +} + +/** + * @brief Disable Power Voltage Detector + * @rmtoll CR2 PVDE LL_PWR_DisablePVD + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisablePVD(void) +{ + CLEAR_BIT(PWR->CR2, PWR_CR2_PVDE); +} + +/** + * @brief Check if Power Voltage Detector is enabled + * @rmtoll CR2 PVDE LL_PWR_IsEnabledPVD + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledPVD(void) +{ + return ((READ_BIT(PWR->CR2, PWR_CR2_PVDE) == (PWR_CR2_PVDE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Internal Wake-up line + * @rmtoll CR3 EIWF LL_PWR_EnableInternWU + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableInternWU(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_EIWF); +} + +/** + * @brief Disable Internal Wake-up line + * @rmtoll CR3 EIWF LL_PWR_DisableInternWU + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableInternWU(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_EIWF); +} + +/** + * @brief Check if Internal Wake-up line is enabled + * @rmtoll CR3 EIWF LL_PWR_IsEnabledInternWU + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledInternWU(void) +{ + return ((READ_BIT(PWR->CR3, PWR_CR3_EIWF) == (PWR_CR3_EIWF)) ? 1UL : 0UL); +} + +/** + * @brief Enable pull-up and pull-down configuration + * @rmtoll CR3 APC LL_PWR_EnablePUPDCfg + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnablePUPDCfg(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_APC); +} + +/** + * @brief Disable pull-up and pull-down configuration + * @rmtoll CR3 APC LL_PWR_DisablePUPDCfg + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisablePUPDCfg(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_APC); +} + +/** + * @brief Check if pull-up and pull-down configuration is enabled + * @rmtoll CR3 APC LL_PWR_IsEnabledPUPDCfg + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledPUPDCfg(void) +{ + return ((READ_BIT(PWR->CR3, PWR_CR3_APC) == (PWR_CR3_APC)) ? 1UL : 0UL); +} + +#if defined(PWR_CR3_DSIPDEN) +/** + * @brief Enable pull-down activation on DSI pins + * @rmtoll CR3 DSIPDEN LL_PWR_EnableDSIPullDown + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableDSIPullDown(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} + +/** + * @brief Disable pull-down activation on DSI pins + * @rmtoll CR3 DSIPDEN LL_PWR_DisableDSIPullDown + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableDSIPullDown(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_DSIPDEN); +} + +/** + * @brief Check if pull-down activation on DSI pins is enabled + * @rmtoll CR3 DSIPDEN LL_PWR_IsEnabledDSIPullDown + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledDSIPullDown(void) +{ + return ((READ_BIT(PWR->CR3, PWR_CR3_DSIPDEN) == (PWR_CR3_DSIPDEN)) ? 1UL : 0UL); +} +#endif /* PWR_CR3_DSIPDEN */ + +#if defined(PWR_CR3_ENULP) +/** + * @brief Enable Ultra Low Power BORL, BORH and PVD for STOP2 and Standby modes + * @rmtoll CR3 ENULP LL_PWR_EnableBORPVD_ULP + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableBORPVD_ULP(void) +{ + SET_BIT(PWR->CR3, PWR_CR3_ENULP); +} + +/** + * @brief Disable Ultra Low Power BORL, BORH and PVD for STOP2 and Standby modes + * @rmtoll CR3 ENULP LL_PWR_DisableBORPVD_ULP + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableBORPVD_ULP(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_ENULP); +} + +/** + * @brief Check if Ultra Low Power BORL, BORH and PVD for STOP2 and Standby modes is enabled + * @rmtoll CR3 ENULP LL_PWR_IsEnabledBORPVD_ULP + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledBORPVD_ULP(void) +{ + return ((READ_BIT(PWR->CR3, PWR_CR3_ENULP) == (PWR_CR3_ENULP)) ? 1UL : 0UL); +} +#endif /* PWR_CR3_ENULP */ + +/** + * @brief Enable SRAM2 full content retention in Standby mode + * @rmtoll CR3 RRS LL_PWR_EnableSRAM2Retention + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableSRAM2Retention(void) +{ + MODIFY_REG(PWR->CR3, PWR_CR3_RRS, LL_PWR_FULL_SRAM2_RETENTION); +} + +/** + * @brief Disable SRAM2 content retention in Standby mode + * @rmtoll CR3 RRS LL_PWR_DisableSRAM2Retention + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableSRAM2Retention(void) +{ + CLEAR_BIT(PWR->CR3, PWR_CR3_RRS); +} + +/** + * @brief Check if SRAM2 full content retention in Standby mode is enabled + * @rmtoll CR3 RRS LL_PWR_IsEnabledSRAM2Retention + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledSRAM2Retention(void) +{ + return ((READ_BIT(PWR->CR3, PWR_CR3_RRS) == (LL_PWR_FULL_SRAM2_RETENTION)) ? 1UL : 0UL); +} + +/** + * @brief Set SRAM2 content retention in Standby mode + * @rmtoll CR3 RRS LL_PWR_SetSRAM2ContentRetention + * @param SRAM2Size This parameter can be one of the following values: + * @arg @ref LL_PWR_NO_SRAM2_RETENTION + * @arg @ref LL_PWR_FULL_SRAM2_RETENTION + * @arg @ref LL_PWR_4KBYTES_SRAM2_RETENTION + * @note LL_PWR_4KBYTES_SRAM2_RETENTION parameter is not available on all devices + * @note Setting LL_PWR_NO_SRAM2_RETENTION is same as calling LL_PWR_DisableSRAM2Retention() + * @note Setting LL_PWR_FULL_SRAM2_RETENTION is same as calling LL_PWR_EnableSRAM2Retention() + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetSRAM2ContentRetention(uint32_t SRAM2Size) +{ + MODIFY_REG(PWR->CR3, PWR_CR3_RRS, SRAM2Size); +} + +/** + * @brief Get SRAM2 content retention in Standby mode + * @rmtoll CR3 RRS LL_PWR_GetSRAM2ContentRetention + * @retval Returned value can be one of the following values: + * @arg @ref LL_PWR_NO_SRAM2_RETENTION + * @arg @ref LL_PWR_FULL_SRAM2_RETENTION + * @arg @ref LL_PWR_4KBYTES_SRAM2_RETENTION + * @note LL_PWR_4KBYTES_SRAM2_RETENTION parameter is not available on all devices + */ +__STATIC_INLINE uint32_t LL_PWR_GetSRAM2ContentRetention(void) +{ + return (uint32_t)(READ_BIT(PWR->CR3, PWR_CR3_RRS)); +} + +/** + * @brief Enable the WakeUp PINx functionality + * @rmtoll CR3 EWUP1 LL_PWR_EnableWakeUpPin\n + * CR3 EWUP2 LL_PWR_EnableWakeUpPin\n + * CR3 EWUP3 LL_PWR_EnableWakeUpPin\n + * CR3 EWUP4 LL_PWR_EnableWakeUpPin\n + * CR3 EWUP5 LL_PWR_EnableWakeUpPin\n + * @param WakeUpPin This parameter can be one of the following values: + * @arg @ref LL_PWR_WAKEUP_PIN1 + * @arg @ref LL_PWR_WAKEUP_PIN2 + * @arg @ref LL_PWR_WAKEUP_PIN3 + * @arg @ref LL_PWR_WAKEUP_PIN4 + * @arg @ref LL_PWR_WAKEUP_PIN5 + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableWakeUpPin(uint32_t WakeUpPin) +{ + SET_BIT(PWR->CR3, WakeUpPin); +} + +/** + * @brief Disable the WakeUp PINx functionality + * @rmtoll CR3 EWUP1 LL_PWR_DisableWakeUpPin\n + * CR3 EWUP2 LL_PWR_DisableWakeUpPin\n + * CR3 EWUP3 LL_PWR_DisableWakeUpPin\n + * CR3 EWUP4 LL_PWR_DisableWakeUpPin\n + * CR3 EWUP5 LL_PWR_DisableWakeUpPin\n + * @param WakeUpPin This parameter can be one of the following values: + * @arg @ref LL_PWR_WAKEUP_PIN1 + * @arg @ref LL_PWR_WAKEUP_PIN2 + * @arg @ref LL_PWR_WAKEUP_PIN3 + * @arg @ref LL_PWR_WAKEUP_PIN4 + * @arg @ref LL_PWR_WAKEUP_PIN5 + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableWakeUpPin(uint32_t WakeUpPin) +{ + CLEAR_BIT(PWR->CR3, WakeUpPin); +} + +/** + * @brief Check if the WakeUp PINx functionality is enabled + * @rmtoll CR3 EWUP1 LL_PWR_IsEnabledWakeUpPin\n + * CR3 EWUP2 LL_PWR_IsEnabledWakeUpPin\n + * CR3 EWUP3 LL_PWR_IsEnabledWakeUpPin\n + * CR3 EWUP4 LL_PWR_IsEnabledWakeUpPin\n + * CR3 EWUP5 LL_PWR_IsEnabledWakeUpPin\n + * @param WakeUpPin This parameter can be one of the following values: + * @arg @ref LL_PWR_WAKEUP_PIN1 + * @arg @ref LL_PWR_WAKEUP_PIN2 + * @arg @ref LL_PWR_WAKEUP_PIN3 + * @arg @ref LL_PWR_WAKEUP_PIN4 + * @arg @ref LL_PWR_WAKEUP_PIN5 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledWakeUpPin(uint32_t WakeUpPin) +{ + return ((READ_BIT(PWR->CR3, WakeUpPin) == (WakeUpPin)) ? 1UL : 0UL); +} + +#if defined(PWR_CR4_EXT_SMPS_ON) +/** + * @brief Enable the CFLDO working @ 0.95V + * @note When external SMPS is used & CFLDO operating in Range 2, the regulated voltage of the + * internal CFLDO can be reduced to 0.95V. + * @rmtoll CR4 EXT_SMPS_ON LL_PWR_EnableExtSMPS_0V95 + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableExtSMPS_0V95(void) +{ + SET_BIT(PWR->CR4, PWR_CR4_EXT_SMPS_ON); +} + +/** + * @brief Disable the CFLDO working @ 0.95V + * @note When external SMPS is used & CFLDO operating in Range 2, the regulated voltage of the + * internal CFLDO can be reduced to 0.95V. + * @rmtoll CR4 EXT_SMPS_ON LL_PWR_DisableExtSMPS_0V95 + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableExtSMPS_0V95(void) +{ + CLEAR_BIT(PWR->CR4, PWR_CR4_EXT_SMPS_ON); +} + +/** + * @brief Check if CFLDO is working @ 0.95V + * @note When external SMPS is used & CFLDO operating in Range 2, the regulated voltage of the + * internal CFLDO can be reduced to 0.95V. + * @rmtoll CR4 EXT_SMPS_ON LL_PWR_IsEnabledExtSMPS_0V95 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledExtSMPS_0V95(void) +{ + return ((READ_BIT(PWR->CR4, PWR_CR4_EXT_SMPS_ON) == (PWR_CR4_EXT_SMPS_ON)) ? 1UL : 0UL); +} +#endif /* PWR_CR4_EXT_SMPS_ON */ + +/** + * @brief Set the resistor impedance + * @rmtoll CR4 VBRS LL_PWR_SetBattChargResistor + * @param Resistor This parameter can be one of the following values: + * @arg @ref LL_PWR_BATT_CHARG_RESISTOR_5K + * @arg @ref LL_PWR_BATT_CHARGRESISTOR_1_5K + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetBattChargResistor(uint32_t Resistor) +{ + MODIFY_REG(PWR->CR4, PWR_CR4_VBRS, Resistor); +} + +/** + * @brief Get the resistor impedance + * @rmtoll CR4 VBRS LL_PWR_GetBattChargResistor + * @retval Returned value can be one of the following values: + * @arg @ref LL_PWR_BATT_CHARG_RESISTOR_5K + * @arg @ref LL_PWR_BATT_CHARGRESISTOR_1_5K + */ +__STATIC_INLINE uint32_t LL_PWR_GetBattChargResistor(void) +{ + return (uint32_t)(READ_BIT(PWR->CR4, PWR_CR4_VBRS)); +} + +/** + * @brief Enable battery charging + * @rmtoll CR4 VBE LL_PWR_EnableBatteryCharging + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableBatteryCharging(void) +{ + SET_BIT(PWR->CR4, PWR_CR4_VBE); +} + +/** + * @brief Disable battery charging + * @rmtoll CR4 VBE LL_PWR_DisableBatteryCharging + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableBatteryCharging(void) +{ + CLEAR_BIT(PWR->CR4, PWR_CR4_VBE); +} + +/** + * @brief Check if battery charging is enabled + * @rmtoll CR4 VBE LL_PWR_IsEnabledBatteryCharging + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledBatteryCharging(void) +{ + return ((READ_BIT(PWR->CR4, PWR_CR4_VBE) == (PWR_CR4_VBE)) ? 1UL : 0UL); +} + +/** + * @brief Set the Wake-Up pin polarity low for the event detection + * @rmtoll CR4 WP1 LL_PWR_SetWakeUpPinPolarityLow\n + * CR4 WP2 LL_PWR_SetWakeUpPinPolarityLow\n + * CR4 WP3 LL_PWR_SetWakeUpPinPolarityLow\n + * CR4 WP4 LL_PWR_SetWakeUpPinPolarityLow\n + * CR4 WP5 LL_PWR_SetWakeUpPinPolarityLow + * @param WakeUpPin This parameter can be one of the following values: + * @arg @ref LL_PWR_WAKEUP_PIN1 + * @arg @ref LL_PWR_WAKEUP_PIN2 + * @arg @ref LL_PWR_WAKEUP_PIN3 + * @arg @ref LL_PWR_WAKEUP_PIN4 + * @arg @ref LL_PWR_WAKEUP_PIN5 + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetWakeUpPinPolarityLow(uint32_t WakeUpPin) +{ + SET_BIT(PWR->CR4, WakeUpPin); +} + +/** + * @brief Set the Wake-Up pin polarity high for the event detection + * @rmtoll CR4 WP1 LL_PWR_SetWakeUpPinPolarityHigh\n + * CR4 WP2 LL_PWR_SetWakeUpPinPolarityHigh\n + * CR4 WP3 LL_PWR_SetWakeUpPinPolarityHigh\n + * CR4 WP4 LL_PWR_SetWakeUpPinPolarityHigh\n + * CR4 WP5 LL_PWR_SetWakeUpPinPolarityHigh + * @param WakeUpPin This parameter can be one of the following values: + * @arg @ref LL_PWR_WAKEUP_PIN1 + * @arg @ref LL_PWR_WAKEUP_PIN2 + * @arg @ref LL_PWR_WAKEUP_PIN3 + * @arg @ref LL_PWR_WAKEUP_PIN4 + * @arg @ref LL_PWR_WAKEUP_PIN5 + * @retval None + */ +__STATIC_INLINE void LL_PWR_SetWakeUpPinPolarityHigh(uint32_t WakeUpPin) +{ + CLEAR_BIT(PWR->CR4, WakeUpPin); +} + +/** + * @brief Get the Wake-Up pin polarity for the event detection + * @rmtoll CR4 WP1 LL_PWR_IsWakeUpPinPolarityLow\n + * CR4 WP2 LL_PWR_IsWakeUpPinPolarityLow\n + * CR4 WP3 LL_PWR_IsWakeUpPinPolarityLow\n + * CR4 WP4 LL_PWR_IsWakeUpPinPolarityLow\n + * CR4 WP5 LL_PWR_IsWakeUpPinPolarityLow + * @param WakeUpPin This parameter can be one of the following values: + * @arg @ref LL_PWR_WAKEUP_PIN1 + * @arg @ref LL_PWR_WAKEUP_PIN2 + * @arg @ref LL_PWR_WAKEUP_PIN3 + * @arg @ref LL_PWR_WAKEUP_PIN4 + * @arg @ref LL_PWR_WAKEUP_PIN5 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsWakeUpPinPolarityLow(uint32_t WakeUpPin) +{ + return ((READ_BIT(PWR->CR4, WakeUpPin) == (WakeUpPin)) ? 1UL : 0UL); +} + +/** + * @brief Enable GPIO pull-up state in Standby and Shutdown modes + * @rmtoll PUCRA PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRB PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRC PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRD PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRE PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRF PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRG PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRH PU0-15 LL_PWR_EnableGPIOPullUp\n + * PUCRI PU0-11 LL_PWR_EnableGPIOPullUp + * @param GPIO This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_A + * @arg @ref LL_PWR_GPIO_B + * @arg @ref LL_PWR_GPIO_C + * @arg @ref LL_PWR_GPIO_D + * @arg @ref LL_PWR_GPIO_E + * @arg @ref LL_PWR_GPIO_F (*) + * @arg @ref LL_PWR_GPIO_G (*) + * @arg @ref LL_PWR_GPIO_H + * @arg @ref LL_PWR_GPIO_I (*) + * + * (*) value not defined in all devices + * @param GPIONumber This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_BIT_0 + * @arg @ref LL_PWR_GPIO_BIT_1 + * @arg @ref LL_PWR_GPIO_BIT_2 + * @arg @ref LL_PWR_GPIO_BIT_3 + * @arg @ref LL_PWR_GPIO_BIT_4 + * @arg @ref LL_PWR_GPIO_BIT_5 + * @arg @ref LL_PWR_GPIO_BIT_6 + * @arg @ref LL_PWR_GPIO_BIT_7 + * @arg @ref LL_PWR_GPIO_BIT_8 + * @arg @ref LL_PWR_GPIO_BIT_9 + * @arg @ref LL_PWR_GPIO_BIT_10 + * @arg @ref LL_PWR_GPIO_BIT_11 + * @arg @ref LL_PWR_GPIO_BIT_12 + * @arg @ref LL_PWR_GPIO_BIT_13 + * @arg @ref LL_PWR_GPIO_BIT_14 + * @arg @ref LL_PWR_GPIO_BIT_15 + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + SET_BIT(*((__IO uint32_t *)GPIO), GPIONumber); +} + +/** + * @brief Disable GPIO pull-up state in Standby and Shutdown modes + * @rmtoll PUCRA PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRB PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRC PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRD PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRE PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRF PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRG PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRH PU0-15 LL_PWR_DisableGPIOPullUp\n + * PUCRI PU0-11 LL_PWR_DisableGPIOPullUp + * @param GPIO This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_A + * @arg @ref LL_PWR_GPIO_B + * @arg @ref LL_PWR_GPIO_C + * @arg @ref LL_PWR_GPIO_D + * @arg @ref LL_PWR_GPIO_E + * @arg @ref LL_PWR_GPIO_F (*) + * @arg @ref LL_PWR_GPIO_G (*) + * @arg @ref LL_PWR_GPIO_H + * @arg @ref LL_PWR_GPIO_I (*) + * + * (*) value not defined in all devices + * @param GPIONumber This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_BIT_0 + * @arg @ref LL_PWR_GPIO_BIT_1 + * @arg @ref LL_PWR_GPIO_BIT_2 + * @arg @ref LL_PWR_GPIO_BIT_3 + * @arg @ref LL_PWR_GPIO_BIT_4 + * @arg @ref LL_PWR_GPIO_BIT_5 + * @arg @ref LL_PWR_GPIO_BIT_6 + * @arg @ref LL_PWR_GPIO_BIT_7 + * @arg @ref LL_PWR_GPIO_BIT_8 + * @arg @ref LL_PWR_GPIO_BIT_9 + * @arg @ref LL_PWR_GPIO_BIT_10 + * @arg @ref LL_PWR_GPIO_BIT_11 + * @arg @ref LL_PWR_GPIO_BIT_12 + * @arg @ref LL_PWR_GPIO_BIT_13 + * @arg @ref LL_PWR_GPIO_BIT_14 + * @arg @ref LL_PWR_GPIO_BIT_15 + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + CLEAR_BIT(*((__IO uint32_t *)GPIO), GPIONumber); +} + +/** + * @brief Check if GPIO pull-up state is enabled + * @rmtoll PUCRA PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRB PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRC PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRD PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRE PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRF PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRG PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRH PU0-15 LL_PWR_IsEnabledGPIOPullUp\n + * PUCRI PU0-11 LL_PWR_IsEnabledGPIOPullUp + * @param GPIO This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_A + * @arg @ref LL_PWR_GPIO_B + * @arg @ref LL_PWR_GPIO_C + * @arg @ref LL_PWR_GPIO_D + * @arg @ref LL_PWR_GPIO_E + * @arg @ref LL_PWR_GPIO_F (*) + * @arg @ref LL_PWR_GPIO_G (*) + * @arg @ref LL_PWR_GPIO_H + * @arg @ref LL_PWR_GPIO_I (*) + * + * (*) value not defined in all devices + * @param GPIONumber This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_BIT_0 + * @arg @ref LL_PWR_GPIO_BIT_1 + * @arg @ref LL_PWR_GPIO_BIT_2 + * @arg @ref LL_PWR_GPIO_BIT_3 + * @arg @ref LL_PWR_GPIO_BIT_4 + * @arg @ref LL_PWR_GPIO_BIT_5 + * @arg @ref LL_PWR_GPIO_BIT_6 + * @arg @ref LL_PWR_GPIO_BIT_7 + * @arg @ref LL_PWR_GPIO_BIT_8 + * @arg @ref LL_PWR_GPIO_BIT_9 + * @arg @ref LL_PWR_GPIO_BIT_10 + * @arg @ref LL_PWR_GPIO_BIT_11 + * @arg @ref LL_PWR_GPIO_BIT_12 + * @arg @ref LL_PWR_GPIO_BIT_13 + * @arg @ref LL_PWR_GPIO_BIT_14 + * @arg @ref LL_PWR_GPIO_BIT_15 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber) +{ + return ((READ_BIT(*((__IO uint32_t *)GPIO), GPIONumber) == (GPIONumber)) ? 1UL : 0UL); +} + +/** + * @brief Enable GPIO pull-down state in Standby and Shutdown modes + * @rmtoll PDCRA PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRB PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRC PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRD PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRE PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRF PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRG PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRH PD0-15 LL_PWR_EnableGPIOPullDown\n + * PDCRI PD0-11 LL_PWR_EnableGPIOPullDown + * @param GPIO This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_A + * @arg @ref LL_PWR_GPIO_B + * @arg @ref LL_PWR_GPIO_C + * @arg @ref LL_PWR_GPIO_D + * @arg @ref LL_PWR_GPIO_E + * @arg @ref LL_PWR_GPIO_F (*) + * @arg @ref LL_PWR_GPIO_G (*) + * @arg @ref LL_PWR_GPIO_H + * @arg @ref LL_PWR_GPIO_I (*) + * + * (*) value not defined in all devices + * @param GPIONumber This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_BIT_0 + * @arg @ref LL_PWR_GPIO_BIT_1 + * @arg @ref LL_PWR_GPIO_BIT_2 + * @arg @ref LL_PWR_GPIO_BIT_3 + * @arg @ref LL_PWR_GPIO_BIT_4 + * @arg @ref LL_PWR_GPIO_BIT_5 + * @arg @ref LL_PWR_GPIO_BIT_6 + * @arg @ref LL_PWR_GPIO_BIT_7 + * @arg @ref LL_PWR_GPIO_BIT_8 + * @arg @ref LL_PWR_GPIO_BIT_9 + * @arg @ref LL_PWR_GPIO_BIT_10 + * @arg @ref LL_PWR_GPIO_BIT_11 + * @arg @ref LL_PWR_GPIO_BIT_12 + * @arg @ref LL_PWR_GPIO_BIT_13 + * @arg @ref LL_PWR_GPIO_BIT_14 + * @arg @ref LL_PWR_GPIO_BIT_15 + * @retval None + */ +__STATIC_INLINE void LL_PWR_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + SET_BIT(*((__IO uint32_t *)(GPIO + 4U)), GPIONumber); +} + +/** + * @brief Disable GPIO pull-down state in Standby and Shutdown modes + * @rmtoll PDCRA PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRB PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRC PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRD PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRE PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRF PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRG PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRH PD0-15 LL_PWR_DisableGPIOPullDown\n + * PDCRI PD0-11 LL_PWR_DisableGPIOPullDown + * @param GPIO This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_A + * @arg @ref LL_PWR_GPIO_B + * @arg @ref LL_PWR_GPIO_C + * @arg @ref LL_PWR_GPIO_D + * @arg @ref LL_PWR_GPIO_E + * @arg @ref LL_PWR_GPIO_F (*) + * @arg @ref LL_PWR_GPIO_G (*) + * @arg @ref LL_PWR_GPIO_H + * @arg @ref LL_PWR_GPIO_I (*) + * + * (*) value not defined in all devices + * @param GPIONumber This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_BIT_0 + * @arg @ref LL_PWR_GPIO_BIT_1 + * @arg @ref LL_PWR_GPIO_BIT_2 + * @arg @ref LL_PWR_GPIO_BIT_3 + * @arg @ref LL_PWR_GPIO_BIT_4 + * @arg @ref LL_PWR_GPIO_BIT_5 + * @arg @ref LL_PWR_GPIO_BIT_6 + * @arg @ref LL_PWR_GPIO_BIT_7 + * @arg @ref LL_PWR_GPIO_BIT_8 + * @arg @ref LL_PWR_GPIO_BIT_9 + * @arg @ref LL_PWR_GPIO_BIT_10 + * @arg @ref LL_PWR_GPIO_BIT_11 + * @arg @ref LL_PWR_GPIO_BIT_12 + * @arg @ref LL_PWR_GPIO_BIT_13 + * @arg @ref LL_PWR_GPIO_BIT_14 + * @arg @ref LL_PWR_GPIO_BIT_15 + * @retval None + */ +__STATIC_INLINE void LL_PWR_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + CLEAR_BIT(*((__IO uint32_t *)(GPIO + 4U)), GPIONumber); +} + +/** + * @brief Check if GPIO pull-down state is enabled + * @rmtoll PDCRA PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRB PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRC PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRD PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRE PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRF PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRG PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRH PD0-15 LL_PWR_IsEnabledGPIOPullDown\n + * PDCRI PD0-11 LL_PWR_IsEnabledGPIOPullDown + * @param GPIO This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_A + * @arg @ref LL_PWR_GPIO_B + * @arg @ref LL_PWR_GPIO_C + * @arg @ref LL_PWR_GPIO_D + * @arg @ref LL_PWR_GPIO_E + * @arg @ref LL_PWR_GPIO_F (*) + * @arg @ref LL_PWR_GPIO_G (*) + * @arg @ref LL_PWR_GPIO_H + * @arg @ref LL_PWR_GPIO_I (*) + * + * (*) value not defined in all devices + * @param GPIONumber This parameter can be one of the following values: + * @arg @ref LL_PWR_GPIO_BIT_0 + * @arg @ref LL_PWR_GPIO_BIT_1 + * @arg @ref LL_PWR_GPIO_BIT_2 + * @arg @ref LL_PWR_GPIO_BIT_3 + * @arg @ref LL_PWR_GPIO_BIT_4 + * @arg @ref LL_PWR_GPIO_BIT_5 + * @arg @ref LL_PWR_GPIO_BIT_6 + * @arg @ref LL_PWR_GPIO_BIT_7 + * @arg @ref LL_PWR_GPIO_BIT_8 + * @arg @ref LL_PWR_GPIO_BIT_9 + * @arg @ref LL_PWR_GPIO_BIT_10 + * @arg @ref LL_PWR_GPIO_BIT_11 + * @arg @ref LL_PWR_GPIO_BIT_12 + * @arg @ref LL_PWR_GPIO_BIT_13 + * @arg @ref LL_PWR_GPIO_BIT_14 + * @arg @ref LL_PWR_GPIO_BIT_15 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsEnabledGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber) +{ + return ((READ_BIT(*((__IO uint32_t *)(GPIO + 4U)), GPIONumber) == (GPIONumber)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup PWR_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Get Internal Wake-up line Flag + * @rmtoll SR1 WUFI LL_PWR_IsActiveFlag_InternWU + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_InternWU(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_WUFI) == (PWR_SR1_WUFI)) ? 1UL : 0UL); +} + +#if defined(PWR_SR1_EXT_SMPS_RDY) +/** + * @brief Get Ready Flag for switching to external SMPS + * @rmtoll SR1 EXT_SMPS_RDY LL_PWR_IsActiveFlag_ExtSMPSReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_ExtSMPSReady(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_EXT_SMPS_RDY) == (PWR_SR1_EXT_SMPS_RDY)) ? 1UL : 0UL); +} +#endif /* PWR_SR1_EXT_SMPS_RDY */ + +/** + * @brief Get Stand-By Flag + * @rmtoll SR1 SBF LL_PWR_IsActiveFlag_SB + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_SB(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_SBF) == (PWR_SR1_SBF)) ? 1UL : 0UL); +} + +/** + * @brief Get Wake-up Flag 5 + * @rmtoll SR1 WUF5 LL_PWR_IsActiveFlag_WU5 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_WU5(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_WUF5) == (PWR_SR1_WUF5)) ? 1UL : 0UL); +} + +/** + * @brief Get Wake-up Flag 4 + * @rmtoll SR1 WUF4 LL_PWR_IsActiveFlag_WU4 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_WU4(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_WUF4) == (PWR_SR1_WUF4)) ? 1UL : 0UL); +} + +/** + * @brief Get Wake-up Flag 3 + * @rmtoll SR1 WUF3 LL_PWR_IsActiveFlag_WU3 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_WU3(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_WUF3) == (PWR_SR1_WUF3)) ? 1UL : 0UL); +} + +/** + * @brief Get Wake-up Flag 2 + * @rmtoll SR1 WUF2 LL_PWR_IsActiveFlag_WU2 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_WU2(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_WUF2) == (PWR_SR1_WUF2)) ? 1UL : 0UL); +} + +/** + * @brief Get Wake-up Flag 1 + * @rmtoll SR1 WUF1 LL_PWR_IsActiveFlag_WU1 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_WU1(void) +{ + return ((READ_BIT(PWR->SR1, PWR_SR1_WUF1) == (PWR_SR1_WUF1)) ? 1UL : 0UL); +} + +/** + * @brief Clear Stand-By Flag + * @rmtoll SCR CSBF LL_PWR_ClearFlag_SB + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_SB(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CSBF); +} + +/** + * @brief Clear Wake-up Flags + * @rmtoll SCR CWUF LL_PWR_ClearFlag_WU + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_WU(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CWUF); +} + +/** + * @brief Clear Wake-up Flag 5 + * @rmtoll SCR CWUF5 LL_PWR_ClearFlag_WU5 + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_WU5(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CWUF5); +} + +/** + * @brief Clear Wake-up Flag 4 + * @rmtoll SCR CWUF4 LL_PWR_ClearFlag_WU4 + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_WU4(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CWUF4); +} + +/** + * @brief Clear Wake-up Flag 3 + * @rmtoll SCR CWUF3 LL_PWR_ClearFlag_WU3 + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_WU3(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CWUF3); +} + +/** + * @brief Clear Wake-up Flag 2 + * @rmtoll SCR CWUF2 LL_PWR_ClearFlag_WU2 + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_WU2(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CWUF2); +} + +/** + * @brief Clear Wake-up Flag 1 + * @rmtoll SCR CWUF1 LL_PWR_ClearFlag_WU1 + * @retval None + */ +__STATIC_INLINE void LL_PWR_ClearFlag_WU1(void) +{ + WRITE_REG(PWR->SCR, PWR_SCR_CWUF1); +} + +/** + * @brief Indicate whether VDDA voltage is below or above PVM4 threshold + * @rmtoll SR2 PVMO4 LL_PWR_IsActiveFlag_PVMO4 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_PVMO4(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_PVMO4) == (PWR_SR2_PVMO4)) ? 1UL : 0UL); +} + +/** + * @brief Indicate whether VDDA voltage is below or above PVM3 threshold + * @rmtoll SR2 PVMO3 LL_PWR_IsActiveFlag_PVMO3 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_PVMO3(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_PVMO3) == (PWR_SR2_PVMO3)) ? 1UL : 0UL); +} + +#if defined(PWR_SR2_PVMO2) +/** + * @brief Indicate whether VDDIO2 voltage is below or above PVM2 threshold + * @rmtoll SR2 PVMO2 LL_PWR_IsActiveFlag_PVMO2 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_PVMO2(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_PVMO2) == (PWR_SR2_PVMO2)) ? 1UL : 0UL); +} +#endif /* PWR_SR2_PVMO2 */ + +#if defined(PWR_SR2_PVMO1) +/** + * @brief Indicate whether VDDUSB voltage is below or above PVM1 threshold + * @rmtoll SR2 PVMO1 LL_PWR_IsActiveFlag_PVMO1 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_PVMO1(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_PVMO1) == (PWR_SR2_PVMO1)) ? 1UL : 0UL); +} +#endif /* PWR_SR2_PVMO1 */ + +/** + * @brief Indicate whether VDD voltage is below or above the selected PVD threshold + * @rmtoll SR2 PVDO LL_PWR_IsActiveFlag_PVDO + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_PVDO(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_PVDO) == (PWR_SR2_PVDO)) ? 1UL : 0UL); +} + +/** + * @brief Indicate whether the regulator is ready in the selected voltage range or if its output voltage is still changing to the required voltage level + * @rmtoll SR2 VOSF LL_PWR_IsActiveFlag_VOS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_VOS(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_VOSF) == (PWR_SR2_VOSF)) ? 1UL : 0UL); +} + +/** + * @brief Indicate whether the regulator is ready in main mode or is in low-power mode + * @note Take care, return value "0" means the regulator is ready. Return value "1" means the output voltage range is still changing. + * @rmtoll SR2 REGLPF LL_PWR_IsActiveFlag_REGLPF + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_REGLPF(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_REGLPF) == (PWR_SR2_REGLPF)) ? 1UL : 0UL); +} + +/** + * @brief Indicate whether or not the low-power regulator is ready + * @rmtoll SR2 REGLPS LL_PWR_IsActiveFlag_REGLPS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_PWR_IsActiveFlag_REGLPS(void) +{ + return ((READ_BIT(PWR->SR2, PWR_SR2_REGLPS) == (PWR_SR2_REGLPS)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup PWR_LL_EF_Init De-initialization function + * @{ + */ +ErrorStatus LL_PWR_DeInit(void); +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup PWR_LL_EF_Legacy_Functions Legacy functions name + * @{ + */ +/* Old functions name kept for legacy purpose, to be replaced by the */ +/* current functions name. */ +#define LL_PWR_IsActiveFlag_VOSF LL_PWR_IsActiveFlag_VOS +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(PWR) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_PWR_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_rcc.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_rcc.h new file mode 100644 index 0000000..6bd72bd --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_rcc.h @@ -0,0 +1,6233 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_rcc.h + * @author MCD Application Team + * @brief Header file of RCC 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 STM32L4xx_LL_RCC_H +#define STM32L4xx_LL_RCC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(RCC) + +/** @defgroup RCC_LL RCC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RCC_LL_Private_Constants RCC Private Constants + * @{ + */ +/* Defines used to perform offsets*/ +/* Offset used to access to RCC_CCIPR and RCC_CCIPR2 registers */ +#define RCC_OFFSET_CCIPR 0U +#define RCC_OFFSET_CCIPR2 0x14U + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RCC_LL_Private_Macros RCC Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RCC_LL_Exported_Types RCC Exported Types + * @{ + */ + +/** @defgroup LL_ES_CLOCK_FREQ Clocks Frequency Structure + * @{ + */ + +/** + * @brief RCC Clocks Frequency Structure + */ +typedef struct +{ + uint32_t SYSCLK_Frequency; /*!< SYSCLK clock frequency */ + uint32_t HCLK_Frequency; /*!< HCLK clock frequency */ + uint32_t PCLK1_Frequency; /*!< PCLK1 clock frequency */ + uint32_t PCLK2_Frequency; /*!< PCLK2 clock frequency */ +} LL_RCC_ClocksTypeDef; + +/** + * @} + */ + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RCC_LL_Exported_Constants RCC Exported Constants + * @{ + */ + +/** @defgroup RCC_LL_EC_OSC_VALUES Oscillator Values adaptation + * @brief Defines used to adapt values of different oscillators + * @note These values could be modified in the user environment according to + * HW set-up. + * @{ + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 8000000U /*!< Value of the HSE oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) +#define HSI_VALUE 16000000U /*!< Value of the HSI oscillator in Hz */ +#endif /* HSI_VALUE */ + +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768U /*!< Value of the LSE oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000U /*!< Value of the LSI oscillator in Hz */ +#endif /* LSI_VALUE */ +#if defined(RCC_HSI48_SUPPORT) + +#if !defined (HSI48_VALUE) +#define HSI48_VALUE 48000000U /*!< Value of the HSI48 oscillator in Hz */ +#endif /* HSI48_VALUE */ +#endif /* RCC_HSI48_SUPPORT */ + +#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) +#define EXTERNAL_SAI1_CLOCK_VALUE 48000U /*!< Value of the SAI1_EXTCLK external oscillator in Hz */ +#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ + +#if !defined (EXTERNAL_SAI2_CLOCK_VALUE) +#define EXTERNAL_SAI2_CLOCK_VALUE 48000U /*!< Value of the SAI2_EXTCLK external oscillator in Hz */ +#endif /* EXTERNAL_SAI2_CLOCK_VALUE */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_RCC_WriteReg function + * @{ + */ +#define LL_RCC_CICR_LSIRDYC RCC_CICR_LSIRDYC /*!< LSI Ready Interrupt Clear */ +#define LL_RCC_CICR_LSERDYC RCC_CICR_LSERDYC /*!< LSE Ready Interrupt Clear */ +#define LL_RCC_CICR_MSIRDYC RCC_CICR_MSIRDYC /*!< MSI Ready Interrupt Clear */ +#define LL_RCC_CICR_HSIRDYC RCC_CICR_HSIRDYC /*!< HSI Ready Interrupt Clear */ +#define LL_RCC_CICR_HSERDYC RCC_CICR_HSERDYC /*!< HSE Ready Interrupt Clear */ +#define LL_RCC_CICR_PLLRDYC RCC_CICR_PLLRDYC /*!< PLL Ready Interrupt Clear */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_CICR_HSI48RDYC RCC_CICR_HSI48RDYC /*!< HSI48 Ready Interrupt Clear */ +#endif /* RCC_HSI48_SUPPORT */ +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_CICR_PLLSAI1RDYC RCC_CICR_PLLSAI1RDYC /*!< PLLSAI1 Ready Interrupt Clear */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define LL_RCC_CICR_PLLSAI2RDYC RCC_CICR_PLLSAI2RDYC /*!< PLLSAI2 Ready Interrupt Clear */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define LL_RCC_CICR_LSECSSC RCC_CICR_LSECSSC /*!< LSE Clock Security System Interrupt Clear */ +#define LL_RCC_CICR_CSSC RCC_CICR_CSSC /*!< Clock Security System Interrupt Clear */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_RCC_ReadReg function + * @{ + */ +#define LL_RCC_CIFR_LSIRDYF RCC_CIFR_LSIRDYF /*!< LSI Ready Interrupt flag */ +#define LL_RCC_CIFR_LSERDYF RCC_CIFR_LSERDYF /*!< LSE Ready Interrupt flag */ +#define LL_RCC_CIFR_MSIRDYF RCC_CIFR_MSIRDYF /*!< MSI Ready Interrupt flag */ +#define LL_RCC_CIFR_HSIRDYF RCC_CIFR_HSIRDYF /*!< HSI Ready Interrupt flag */ +#define LL_RCC_CIFR_HSERDYF RCC_CIFR_HSERDYF /*!< HSE Ready Interrupt flag */ +#define LL_RCC_CIFR_PLLRDYF RCC_CIFR_PLLRDYF /*!< PLL Ready Interrupt flag */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_CIFR_HSI48RDYF RCC_CIFR_HSI48RDYF /*!< HSI48 Ready Interrupt flag */ +#endif /* RCC_HSI48_SUPPORT */ +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_CIFR_PLLSAI1RDYF RCC_CIFR_PLLSAI1RDYF /*!< PLLSAI1 Ready Interrupt flag */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define LL_RCC_CIFR_PLLSAI2RDYF RCC_CIFR_PLLSAI2RDYF /*!< PLLSAI2 Ready Interrupt flag */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define LL_RCC_CIFR_LSECSSF RCC_CIFR_LSECSSF /*!< LSE Clock Security System Interrupt flag */ +#define LL_RCC_CIFR_CSSF RCC_CIFR_CSSF /*!< Clock Security System Interrupt flag */ +#define LL_RCC_CSR_FWRSTF RCC_CSR_FWRSTF /*!< Firewall reset flag */ +#define LL_RCC_CSR_LPWRRSTF RCC_CSR_LPWRRSTF /*!< Low-Power reset flag */ +#define LL_RCC_CSR_OBLRSTF RCC_CSR_OBLRSTF /*!< OBL reset flag */ +#define LL_RCC_CSR_PINRSTF RCC_CSR_PINRSTF /*!< PIN reset flag */ +#define LL_RCC_CSR_SFTRSTF RCC_CSR_SFTRSTF /*!< Software Reset flag */ +#define LL_RCC_CSR_IWDGRSTF RCC_CSR_IWDGRSTF /*!< Independent Watchdog reset flag */ +#define LL_RCC_CSR_WWDGRSTF RCC_CSR_WWDGRSTF /*!< Window watchdog reset flag */ +#define LL_RCC_CSR_BORRSTF RCC_CSR_BORRSTF /*!< BOR reset flag */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_RCC_ReadReg and LL_RCC_WriteReg functions + * @{ + */ +#define LL_RCC_CIER_LSIRDYIE RCC_CIER_LSIRDYIE /*!< LSI Ready Interrupt Enable */ +#define LL_RCC_CIER_LSERDYIE RCC_CIER_LSERDYIE /*!< LSE Ready Interrupt Enable */ +#define LL_RCC_CIER_MSIRDYIE RCC_CIER_MSIRDYIE /*!< MSI Ready Interrupt Enable */ +#define LL_RCC_CIER_HSIRDYIE RCC_CIER_HSIRDYIE /*!< HSI Ready Interrupt Enable */ +#define LL_RCC_CIER_HSERDYIE RCC_CIER_HSERDYIE /*!< HSE Ready Interrupt Enable */ +#define LL_RCC_CIER_PLLRDYIE RCC_CIER_PLLRDYIE /*!< PLL Ready Interrupt Enable */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_CIER_HSI48RDYIE RCC_CIER_HSI48RDYIE /*!< HSI48 Ready Interrupt Enable */ +#endif /* RCC_HSI48_SUPPORT */ +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_CIER_PLLSAI1RDYIE RCC_CIER_PLLSAI1RDYIE /*!< PLLSAI1 Ready Interrupt Enable */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define LL_RCC_CIER_PLLSAI2RDYIE RCC_CIER_PLLSAI2RDYIE /*!< PLLSAI2 Ready Interrupt Enable */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define LL_RCC_CIER_LSECSSIE RCC_CIER_LSECSSIE /*!< LSE CSS Interrupt Enable */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_LSEDRIVE LSE oscillator drive capability + * @{ + */ +#define LL_RCC_LSEDRIVE_LOW 0x00000000U /*!< Xtal mode lower driving capability */ +#define LL_RCC_LSEDRIVE_MEDIUMLOW RCC_BDCR_LSEDRV_0 /*!< Xtal mode medium low driving capability */ +#define LL_RCC_LSEDRIVE_MEDIUMHIGH RCC_BDCR_LSEDRV_1 /*!< Xtal mode medium high driving capability */ +#define LL_RCC_LSEDRIVE_HIGH RCC_BDCR_LSEDRV /*!< Xtal mode higher driving capability */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_MSIRANGE MSI clock ranges + * @{ + */ +#define LL_RCC_MSIRANGE_0 RCC_CR_MSIRANGE_0 /*!< MSI = 100 KHz */ +#define LL_RCC_MSIRANGE_1 RCC_CR_MSIRANGE_1 /*!< MSI = 200 KHz */ +#define LL_RCC_MSIRANGE_2 RCC_CR_MSIRANGE_2 /*!< MSI = 400 KHz */ +#define LL_RCC_MSIRANGE_3 RCC_CR_MSIRANGE_3 /*!< MSI = 800 KHz */ +#define LL_RCC_MSIRANGE_4 RCC_CR_MSIRANGE_4 /*!< MSI = 1 MHz */ +#define LL_RCC_MSIRANGE_5 RCC_CR_MSIRANGE_5 /*!< MSI = 2 MHz */ +#define LL_RCC_MSIRANGE_6 RCC_CR_MSIRANGE_6 /*!< MSI = 4 MHz */ +#define LL_RCC_MSIRANGE_7 RCC_CR_MSIRANGE_7 /*!< MSI = 8 MHz */ +#define LL_RCC_MSIRANGE_8 RCC_CR_MSIRANGE_8 /*!< MSI = 16 MHz */ +#define LL_RCC_MSIRANGE_9 RCC_CR_MSIRANGE_9 /*!< MSI = 24 MHz */ +#define LL_RCC_MSIRANGE_10 RCC_CR_MSIRANGE_10 /*!< MSI = 32 MHz */ +#define LL_RCC_MSIRANGE_11 RCC_CR_MSIRANGE_11 /*!< MSI = 48 MHz */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_MSISRANGE MSI range after Standby mode + * @{ + */ +#define LL_RCC_MSISRANGE_4 RCC_CSR_MSISRANGE_1 /*!< MSI = 1 MHz */ +#define LL_RCC_MSISRANGE_5 RCC_CSR_MSISRANGE_2 /*!< MSI = 2 MHz */ +#define LL_RCC_MSISRANGE_6 RCC_CSR_MSISRANGE_4 /*!< MSI = 4 MHz */ +#define LL_RCC_MSISRANGE_7 RCC_CSR_MSISRANGE_8 /*!< MSI = 8 MHz */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_LSCO_CLKSOURCE LSCO Selection + * @{ + */ +#define LL_RCC_LSCO_CLKSOURCE_LSI 0x00000000U /*!< LSI selection for low speed clock */ +#define LL_RCC_LSCO_CLKSOURCE_LSE RCC_BDCR_LSCOSEL /*!< LSE selection for low speed clock */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_SYS_CLKSOURCE System clock switch + * @{ + */ +#define LL_RCC_SYS_CLKSOURCE_MSI RCC_CFGR_SW_MSI /*!< MSI selection as system clock */ +#define LL_RCC_SYS_CLKSOURCE_HSI RCC_CFGR_SW_HSI /*!< HSI selection as system clock */ +#define LL_RCC_SYS_CLKSOURCE_HSE RCC_CFGR_SW_HSE /*!< HSE selection as system clock */ +#define LL_RCC_SYS_CLKSOURCE_PLL RCC_CFGR_SW_PLL /*!< PLL selection as system clock */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_SYS_CLKSOURCE_STATUS System clock switch status + * @{ + */ +#define LL_RCC_SYS_CLKSOURCE_STATUS_MSI RCC_CFGR_SWS_MSI /*!< MSI used as system clock */ +#define LL_RCC_SYS_CLKSOURCE_STATUS_HSI RCC_CFGR_SWS_HSI /*!< HSI used as system clock */ +#define LL_RCC_SYS_CLKSOURCE_STATUS_HSE RCC_CFGR_SWS_HSE /*!< HSE used as system clock */ +#define LL_RCC_SYS_CLKSOURCE_STATUS_PLL RCC_CFGR_SWS_PLL /*!< PLL used as system clock */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_SYSCLK_DIV AHB prescaler + * @{ + */ +#define LL_RCC_SYSCLK_DIV_1 RCC_CFGR_HPRE_DIV1 /*!< SYSCLK not divided */ +#define LL_RCC_SYSCLK_DIV_2 RCC_CFGR_HPRE_DIV2 /*!< SYSCLK divided by 2 */ +#define LL_RCC_SYSCLK_DIV_4 RCC_CFGR_HPRE_DIV4 /*!< SYSCLK divided by 4 */ +#define LL_RCC_SYSCLK_DIV_8 RCC_CFGR_HPRE_DIV8 /*!< SYSCLK divided by 8 */ +#define LL_RCC_SYSCLK_DIV_16 RCC_CFGR_HPRE_DIV16 /*!< SYSCLK divided by 16 */ +#define LL_RCC_SYSCLK_DIV_64 RCC_CFGR_HPRE_DIV64 /*!< SYSCLK divided by 64 */ +#define LL_RCC_SYSCLK_DIV_128 RCC_CFGR_HPRE_DIV128 /*!< SYSCLK divided by 128 */ +#define LL_RCC_SYSCLK_DIV_256 RCC_CFGR_HPRE_DIV256 /*!< SYSCLK divided by 256 */ +#define LL_RCC_SYSCLK_DIV_512 RCC_CFGR_HPRE_DIV512 /*!< SYSCLK divided by 512 */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_APB1_DIV APB low-speed prescaler (APB1) + * @{ + */ +#define LL_RCC_APB1_DIV_1 RCC_CFGR_PPRE1_DIV1 /*!< HCLK not divided */ +#define LL_RCC_APB1_DIV_2 RCC_CFGR_PPRE1_DIV2 /*!< HCLK divided by 2 */ +#define LL_RCC_APB1_DIV_4 RCC_CFGR_PPRE1_DIV4 /*!< HCLK divided by 4 */ +#define LL_RCC_APB1_DIV_8 RCC_CFGR_PPRE1_DIV8 /*!< HCLK divided by 8 */ +#define LL_RCC_APB1_DIV_16 RCC_CFGR_PPRE1_DIV16 /*!< HCLK divided by 16 */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_APB2_DIV APB high-speed prescaler (APB2) + * @{ + */ +#define LL_RCC_APB2_DIV_1 RCC_CFGR_PPRE2_DIV1 /*!< HCLK not divided */ +#define LL_RCC_APB2_DIV_2 RCC_CFGR_PPRE2_DIV2 /*!< HCLK divided by 2 */ +#define LL_RCC_APB2_DIV_4 RCC_CFGR_PPRE2_DIV4 /*!< HCLK divided by 4 */ +#define LL_RCC_APB2_DIV_8 RCC_CFGR_PPRE2_DIV8 /*!< HCLK divided by 8 */ +#define LL_RCC_APB2_DIV_16 RCC_CFGR_PPRE2_DIV16 /*!< HCLK divided by 16 */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_STOP_WAKEUPCLOCK Wakeup from Stop and CSS backup clock selection + * @{ + */ +#define LL_RCC_STOP_WAKEUPCLOCK_MSI 0x00000000U /*!< MSI selection after wake-up from STOP */ +#define LL_RCC_STOP_WAKEUPCLOCK_HSI RCC_CFGR_STOPWUCK /*!< HSI selection after wake-up from STOP */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_MCO1SOURCE MCO1 SOURCE selection + * @{ + */ +#define LL_RCC_MCO1SOURCE_NOCLOCK 0x00000000U /*!< MCO output disabled, no clock on MCO */ +#define LL_RCC_MCO1SOURCE_SYSCLK RCC_CFGR_MCOSEL_0 /*!< SYSCLK selection as MCO1 source */ +#define LL_RCC_MCO1SOURCE_MSI RCC_CFGR_MCOSEL_1 /*!< MSI selection as MCO1 source */ +#define LL_RCC_MCO1SOURCE_HSI (RCC_CFGR_MCOSEL_0| RCC_CFGR_MCOSEL_1) /*!< HSI16 selection as MCO1 source */ +#define LL_RCC_MCO1SOURCE_HSE RCC_CFGR_MCOSEL_2 /*!< HSE selection as MCO1 source */ +#define LL_RCC_MCO1SOURCE_PLLCLK (RCC_CFGR_MCOSEL_0|RCC_CFGR_MCOSEL_2) /*!< Main PLL selection as MCO1 source */ +#define LL_RCC_MCO1SOURCE_LSI (RCC_CFGR_MCOSEL_1|RCC_CFGR_MCOSEL_2) /*!< LSI selection as MCO1 source */ +#define LL_RCC_MCO1SOURCE_LSE (RCC_CFGR_MCOSEL_0|RCC_CFGR_MCOSEL_1|RCC_CFGR_MCOSEL_2) /*!< LSE selection as MCO1 source */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_MCO1SOURCE_HSI48 RCC_CFGR_MCOSEL_3 /*!< HSI48 selection as MCO1 source */ +#endif /* RCC_HSI48_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_MCO1_DIV MCO1 prescaler + * @{ + */ +#define LL_RCC_MCO1_DIV_1 RCC_CFGR_MCOPRE_DIV1 /*!< MCO not divided */ +#define LL_RCC_MCO1_DIV_2 RCC_CFGR_MCOPRE_DIV2 /*!< MCO divided by 2 */ +#define LL_RCC_MCO1_DIV_4 RCC_CFGR_MCOPRE_DIV4 /*!< MCO divided by 4 */ +#define LL_RCC_MCO1_DIV_8 RCC_CFGR_MCOPRE_DIV8 /*!< MCO divided by 8 */ +#define LL_RCC_MCO1_DIV_16 RCC_CFGR_MCOPRE_DIV16 /*!< MCO divided by 16 */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RCC_LL_EC_PERIPH_FREQUENCY Peripheral clock frequency + * @{ + */ +#define LL_RCC_PERIPH_FREQUENCY_NO 0x00000000U /*!< No clock enabled for the peripheral */ +#define LL_RCC_PERIPH_FREQUENCY_NA 0xFFFFFFFFU /*!< Frequency cannot be provided as external clock */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup RCC_LL_EC_USART1_CLKSOURCE Peripheral USART clock source selection + * @{ + */ +#define LL_RCC_USART1_CLKSOURCE_PCLK2 (RCC_CCIPR_USART1SEL << 16U) /*!< PCLK2 clock used as USART1 clock source */ +#define LL_RCC_USART1_CLKSOURCE_SYSCLK ((RCC_CCIPR_USART1SEL << 16U) | RCC_CCIPR_USART1SEL_0) /*!< SYSCLK clock used as USART1 clock source */ +#define LL_RCC_USART1_CLKSOURCE_HSI ((RCC_CCIPR_USART1SEL << 16U) | RCC_CCIPR_USART1SEL_1) /*!< HSI clock used as USART1 clock source */ +#define LL_RCC_USART1_CLKSOURCE_LSE ((RCC_CCIPR_USART1SEL << 16U) | RCC_CCIPR_USART1SEL) /*!< LSE clock used as USART1 clock source */ +#define LL_RCC_USART2_CLKSOURCE_PCLK1 (RCC_CCIPR_USART2SEL << 16U) /*!< PCLK1 clock used as USART2 clock source */ +#define LL_RCC_USART2_CLKSOURCE_SYSCLK ((RCC_CCIPR_USART2SEL << 16U) | RCC_CCIPR_USART2SEL_0) /*!< SYSCLK clock used as USART2 clock source */ +#define LL_RCC_USART2_CLKSOURCE_HSI ((RCC_CCIPR_USART2SEL << 16U) | RCC_CCIPR_USART2SEL_1) /*!< HSI clock used as USART2 clock source */ +#define LL_RCC_USART2_CLKSOURCE_LSE ((RCC_CCIPR_USART2SEL << 16U) | RCC_CCIPR_USART2SEL) /*!< LSE clock used as USART2 clock source */ +#if defined(RCC_CCIPR_USART3SEL) +#define LL_RCC_USART3_CLKSOURCE_PCLK1 (RCC_CCIPR_USART3SEL << 16U) /*!< PCLK1 clock used as USART3 clock source */ +#define LL_RCC_USART3_CLKSOURCE_SYSCLK ((RCC_CCIPR_USART3SEL << 16U) | RCC_CCIPR_USART3SEL_0) /*!< SYSCLK clock used as USART3 clock source */ +#define LL_RCC_USART3_CLKSOURCE_HSI ((RCC_CCIPR_USART3SEL << 16U) | RCC_CCIPR_USART3SEL_1) /*!< HSI clock used as USART3 clock source */ +#define LL_RCC_USART3_CLKSOURCE_LSE ((RCC_CCIPR_USART3SEL << 16U) | RCC_CCIPR_USART3SEL) /*!< LSE clock used as USART3 clock source */ +#endif /* RCC_CCIPR_USART3SEL */ +/** + * @} + */ + +#if defined(RCC_CCIPR_UART4SEL) || defined(RCC_CCIPR_UART5SEL) +/** @defgroup RCC_LL_EC_UART4_CLKSOURCE Peripheral UART clock source selection + * @{ + */ +#if defined(RCC_CCIPR_UART4SEL) +#define LL_RCC_UART4_CLKSOURCE_PCLK1 (RCC_CCIPR_UART4SEL << 16U) /*!< PCLK1 clock used as UART4 clock source */ +#define LL_RCC_UART4_CLKSOURCE_SYSCLK ((RCC_CCIPR_UART4SEL << 16U) | RCC_CCIPR_UART4SEL_0) /*!< SYSCLK clock used as UART4 clock source */ +#define LL_RCC_UART4_CLKSOURCE_HSI ((RCC_CCIPR_UART4SEL << 16U) | RCC_CCIPR_UART4SEL_1) /*!< HSI clock used as UART4 clock source */ +#define LL_RCC_UART4_CLKSOURCE_LSE ((RCC_CCIPR_UART4SEL << 16U) | RCC_CCIPR_UART4SEL) /*!< LSE clock used as UART4 clock source */ +#endif /* RCC_CCIPR_UART4SEL */ +#if defined(RCC_CCIPR_UART5SEL) +#define LL_RCC_UART5_CLKSOURCE_PCLK1 (RCC_CCIPR_UART5SEL << 16U) /*!< PCLK1 clock used as UART5 clock source */ +#define LL_RCC_UART5_CLKSOURCE_SYSCLK ((RCC_CCIPR_UART5SEL << 16U) | RCC_CCIPR_UART5SEL_0) /*!< SYSCLK clock used as UART5 clock source */ +#define LL_RCC_UART5_CLKSOURCE_HSI ((RCC_CCIPR_UART5SEL << 16U) | RCC_CCIPR_UART5SEL_1) /*!< HSI clock used as UART5 clock source */ +#define LL_RCC_UART5_CLKSOURCE_LSE ((RCC_CCIPR_UART5SEL << 16U) | RCC_CCIPR_UART5SEL) /*!< LSE clock used as UART5 clock source */ +#endif /* RCC_CCIPR_UART5SEL */ +/** + * @} + */ +#endif /* RCC_CCIPR_UART4SEL || RCC_CCIPR_UART5SEL */ + +/** @defgroup RCC_LL_EC_LPUART1_CLKSOURCE Peripheral LPUART clock source selection + * @{ + */ +#define LL_RCC_LPUART1_CLKSOURCE_PCLK1 0x00000000U /*!< PCLK1 clock used as LPUART1 clock source */ +#define LL_RCC_LPUART1_CLKSOURCE_SYSCLK RCC_CCIPR_LPUART1SEL_0 /*!< SYSCLK clock used as LPUART1 clock source */ +#define LL_RCC_LPUART1_CLKSOURCE_HSI RCC_CCIPR_LPUART1SEL_1 /*!< HSI clock used as LPUART1 clock source */ +#define LL_RCC_LPUART1_CLKSOURCE_LSE RCC_CCIPR_LPUART1SEL /*!< LSE clock used as LPUART1 clock source */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_I2C1_CLKSOURCE Peripheral I2C clock source selection + * @{ + */ +#define LL_RCC_I2C1_CLKSOURCE_PCLK1 (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C1SEL_Pos << 16U)) /*!< PCLK1 clock used as I2C1 clock source */ +#define LL_RCC_I2C1_CLKSOURCE_SYSCLK (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C1SEL_Pos << 16U) | (RCC_CCIPR_I2C1SEL_0 >> RCC_CCIPR_I2C1SEL_Pos)) /*!< SYSCLK clock used as I2C1 clock source */ +#define LL_RCC_I2C1_CLKSOURCE_HSI (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C1SEL_Pos << 16U) | (RCC_CCIPR_I2C1SEL_1 >> RCC_CCIPR_I2C1SEL_Pos)) /*!< HSI clock used as I2C1 clock source */ +#if defined(RCC_CCIPR_I2C2SEL) +#define LL_RCC_I2C2_CLKSOURCE_PCLK1 (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C2SEL_Pos << 16U)) /*!< PCLK1 clock used as I2C2 clock source */ +#define LL_RCC_I2C2_CLKSOURCE_SYSCLK (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C2SEL_Pos << 16U) | (RCC_CCIPR_I2C2SEL_0 >> RCC_CCIPR_I2C2SEL_Pos)) /*!< SYSCLK clock used as I2C2 clock source */ +#define LL_RCC_I2C2_CLKSOURCE_HSI (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C2SEL_Pos << 16U) | (RCC_CCIPR_I2C2SEL_1 >> RCC_CCIPR_I2C2SEL_Pos)) /*!< HSI clock used as I2C2 clock source */ +#endif /* RCC_CCIPR_I2C2SEL */ +#define LL_RCC_I2C3_CLKSOURCE_PCLK1 (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C3SEL_Pos << 16U)) /*!< PCLK1 clock used as I2C3 clock source */ +#define LL_RCC_I2C3_CLKSOURCE_SYSCLK (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C3SEL_Pos << 16U) | (RCC_CCIPR_I2C3SEL_0 >> RCC_CCIPR_I2C3SEL_Pos)) /*!< SYSCLK clock used as I2C3 clock source */ +#define LL_RCC_I2C3_CLKSOURCE_HSI (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C3SEL_Pos << 16U) | (RCC_CCIPR_I2C3SEL_1 >> RCC_CCIPR_I2C3SEL_Pos)) /*!< HSI clock used as I2C3 clock source */ +#if defined(RCC_CCIPR2_I2C4SEL) +#define LL_RCC_I2C4_CLKSOURCE_PCLK1 (((uint32_t)RCC_OFFSET_CCIPR2 << 24U) | ((uint32_t)RCC_CCIPR2_I2C4SEL_Pos << 16U)) /*!< PCLK1 clock used as I2C4 clock source */ +#define LL_RCC_I2C4_CLKSOURCE_SYSCLK (((uint32_t)RCC_OFFSET_CCIPR2 << 24U) | ((uint32_t)RCC_CCIPR2_I2C4SEL_Pos << 16U) | (RCC_CCIPR2_I2C4SEL_0 >> RCC_CCIPR2_I2C4SEL_Pos)) /*!< SYSCLK clock used as I2C4 clock source */ +#define LL_RCC_I2C4_CLKSOURCE_HSI (((uint32_t)RCC_OFFSET_CCIPR2 << 24U) | ((uint32_t)RCC_CCIPR2_I2C4SEL_Pos << 16U) | (RCC_CCIPR2_I2C4SEL_1 >> RCC_CCIPR2_I2C4SEL_Pos)) /*!< HSI clock used as I2C4 clock source */ +#endif /* RCC_CCIPR2_I2C4SEL */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_LPTIM1_CLKSOURCE Peripheral LPTIM clock source selection + * @{ + */ +#define LL_RCC_LPTIM1_CLKSOURCE_PCLK1 RCC_CCIPR_LPTIM1SEL /*!< PCLK1 clock used as LPTIM1 clock source */ +#define LL_RCC_LPTIM1_CLKSOURCE_LSI (RCC_CCIPR_LPTIM1SEL | (RCC_CCIPR_LPTIM1SEL_0 >> 16U)) /*!< LSI clock used as LPTIM1 clock source */ +#define LL_RCC_LPTIM1_CLKSOURCE_HSI (RCC_CCIPR_LPTIM1SEL | (RCC_CCIPR_LPTIM1SEL_1 >> 16U)) /*!< HSI clock used as LPTIM1 clock source */ +#define LL_RCC_LPTIM1_CLKSOURCE_LSE (RCC_CCIPR_LPTIM1SEL | (RCC_CCIPR_LPTIM1SEL >> 16U)) /*!< LSE clock used as LPTIM1 clock source */ +#define LL_RCC_LPTIM2_CLKSOURCE_PCLK1 RCC_CCIPR_LPTIM2SEL /*!< PCLK1 clock used as LPTIM2 clock source */ +#define LL_RCC_LPTIM2_CLKSOURCE_LSI (RCC_CCIPR_LPTIM2SEL | (RCC_CCIPR_LPTIM2SEL_0 >> 16U)) /*!< LSI clock used as LPTIM2 clock source */ +#define LL_RCC_LPTIM2_CLKSOURCE_HSI (RCC_CCIPR_LPTIM2SEL | (RCC_CCIPR_LPTIM2SEL_1 >> 16U)) /*!< HSI clock used as LPTIM2 clock source */ +#define LL_RCC_LPTIM2_CLKSOURCE_LSE (RCC_CCIPR_LPTIM2SEL | (RCC_CCIPR_LPTIM2SEL >> 16U)) /*!< LSE clock used as LPTIM2 clock source */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_SAI1_CLKSOURCE Peripheral SAI clock source selection + * @{ + */ +#if defined(RCC_CCIPR2_SAI1SEL) +#define LL_RCC_SAI1_CLKSOURCE_PLLSAI1 (RCC_CCIPR2_SAI1SEL << 16U) /*!< PLLSAI1 (PLLSAI1CLK) clock used as SAI1 clock source */ +#define LL_RCC_SAI1_CLKSOURCE_PLLSAI2 ((RCC_CCIPR2_SAI1SEL << 16U) | RCC_CCIPR2_SAI1SEL_0) /*!< PLLSAI2 (PLLSAI2CLK) clock used as SAI1 clock source */ +#define LL_RCC_SAI1_CLKSOURCE_PLL ((RCC_CCIPR2_SAI1SEL << 16U) | RCC_CCIPR2_SAI1SEL_1) /*!< PLL (PLLSAI3CLK) clock used as SAI1 clock source */ +#define LL_RCC_SAI1_CLKSOURCE_PIN ((RCC_CCIPR2_SAI1SEL << 16U) | (RCC_CCIPR2_SAI1SEL_1 | RCC_CCIPR2_SAI1SEL_0)) /*!< External input clock used as SAI1 clock source */ +#define LL_RCC_SAI1_CLKSOURCE_HSI ((RCC_CCIPR2_SAI1SEL << 16U) | RCC_CCIPR2_SAI1SEL_2) /*!< HSI clock used as SAI1 clock source */ +#elif defined(RCC_CCIPR_SAI1SEL) +#define LL_RCC_SAI1_CLKSOURCE_PLLSAI1 RCC_CCIPR_SAI1SEL /*!< PLLSAI1 clock used as SAI1 clock source */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define LL_RCC_SAI1_CLKSOURCE_PLLSAI2 (RCC_CCIPR_SAI1SEL | (RCC_CCIPR_SAI1SEL_0 >> 16U)) /*!< PLLSAI2 clock used as SAI1 clock source */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define LL_RCC_SAI1_CLKSOURCE_PLL (RCC_CCIPR_SAI1SEL | (RCC_CCIPR_SAI1SEL_1 >> 16U)) /*!< PLL clock used as SAI1 clock source */ +#define LL_RCC_SAI1_CLKSOURCE_PIN (RCC_CCIPR_SAI1SEL | (RCC_CCIPR_SAI1SEL >> 16U)) /*!< External input clock used as SAI1 clock source */ +#endif /* RCC_CCIPR2_SAI1SEL */ + +#if defined(RCC_CCIPR2_SAI2SEL) +#define LL_RCC_SAI2_CLKSOURCE_PLLSAI1 (RCC_CCIPR2_SAI2SEL << 16U) /*!< PLLSAI1 (PLLSAI1CLK) clock used as SAI2 clock source */ +#define LL_RCC_SAI2_CLKSOURCE_PLLSAI2 ((RCC_CCIPR2_SAI2SEL << 16U) | RCC_CCIPR2_SAI2SEL_0) /*!< PLLSAI2 (PLLSAI2CLK) clock used as SAI2 clock source */ +#define LL_RCC_SAI2_CLKSOURCE_PLL ((RCC_CCIPR2_SAI2SEL << 16U) | RCC_CCIPR2_SAI2SEL_1) /*!< PLL (PLLSAI3CLK) clock used as SAI2 clock source */ +#define LL_RCC_SAI2_CLKSOURCE_PIN ((RCC_CCIPR2_SAI2SEL << 16U) | (RCC_CCIPR2_SAI2SEL_1 | RCC_CCIPR2_SAI2SEL_0)) /*!< External input clock used as SAI2 clock source */ +#define LL_RCC_SAI2_CLKSOURCE_HSI ((RCC_CCIPR2_SAI2SEL << 16U) | RCC_CCIPR2_SAI2SEL_2) /*!< HSI clock used as SAI2 clock source */ +#elif defined(RCC_CCIPR_SAI2SEL) +#define LL_RCC_SAI2_CLKSOURCE_PLLSAI1 RCC_CCIPR_SAI2SEL /*!< PLLSAI1 clock used as SAI2 clock source */ +#if defined(RCC_PLLSAI2_SUPPORT) +#define LL_RCC_SAI2_CLKSOURCE_PLLSAI2 (RCC_CCIPR_SAI2SEL | (RCC_CCIPR_SAI2SEL_0 >> 16U)) /*!< PLLSAI2 clock used as SAI2 clock source */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#define LL_RCC_SAI2_CLKSOURCE_PLL (RCC_CCIPR_SAI2SEL | (RCC_CCIPR_SAI2SEL_1 >> 16U)) /*!< PLL clock used as SAI2 clock source */ +#define LL_RCC_SAI2_CLKSOURCE_PIN (RCC_CCIPR_SAI2SEL | (RCC_CCIPR_SAI2SEL >> 16U)) /*!< External input clock used as SAI2 clock source */ +#endif /* RCC_CCIPR2_SAI2SEL */ +/** + * @} + */ + +#if defined(RCC_CCIPR2_SDMMCSEL) +/** @defgroup RCC_LL_EC_SDMMC1_KERNELCLKSOURCE Peripheral SDMMC kernel clock source selection + * @{ + */ +#define LL_RCC_SDMMC1_KERNELCLKSOURCE_48CLK 0x00000000U /*!< 48MHz clock from internal multiplexor used as SDMMC1 clock source */ +#define LL_RCC_SDMMC1_KERNELCLKSOURCE_PLLP RCC_CCIPR2_SDMMCSEL /*!< PLLSAI3CLK clock used as SDMMC1 clock source */ +/** + * @} + */ +#endif /* RCC_CCIPR2_SDMMCSEL */ + +#if defined(SDMMC1) +/** @defgroup RCC_LL_EC_SDMMC1_CLKSOURCE Peripheral SDMMC clock source selection + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_SDMMC1_CLKSOURCE_HSI48 0x00000000U /*!< HSI48 clock used as SDMMC1 clock source */ +#else +#define LL_RCC_SDMMC1_CLKSOURCE_NONE 0x00000000U /*!< No clock used as SDMMC1 clock source */ +#endif +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 /*!< PLLSAI1 clock used as SDMMC1 clock source */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#define LL_RCC_SDMMC1_CLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 /*!< PLL clock used as SDMMC1 clock source */ +#define LL_RCC_SDMMC1_CLKSOURCE_MSI RCC_CCIPR_CLK48SEL /*!< MSI clock used as SDMMC1 clock source */ +/** + * @} + */ +#endif /* SDMMC1 */ + +/** @defgroup RCC_LL_EC_RNG_CLKSOURCE Peripheral RNG clock source selection + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_RNG_CLKSOURCE_HSI48 0x00000000U /*!< HSI48 clock used as RNG clock source */ +#else +#define LL_RCC_RNG_CLKSOURCE_NONE 0x00000000U /*!< No clock used as RNG clock source */ +#endif +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_RNG_CLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 /*!< PLLSAI1 clock used as RNG clock source */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#define LL_RCC_RNG_CLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 /*!< PLL clock used as RNG clock source */ +#define LL_RCC_RNG_CLKSOURCE_MSI RCC_CCIPR_CLK48SEL /*!< MSI clock used as RNG clock source */ +/** + * @} + */ + +#if defined(USB_OTG_FS) || defined(USB) +/** @defgroup RCC_LL_EC_USB_CLKSOURCE Peripheral USB clock source selection + * @{ + */ +#if defined(RCC_HSI48_SUPPORT) +#define LL_RCC_USB_CLKSOURCE_HSI48 0x00000000U /*!< HSI48 clock used as USB clock source */ +#else +#define LL_RCC_USB_CLKSOURCE_NONE 0x00000000U /*!< No clock used as USB clock source */ +#endif +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_USB_CLKSOURCE_PLLSAI1 RCC_CCIPR_CLK48SEL_0 /*!< PLLSAI1 clock used as USB clock source */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#define LL_RCC_USB_CLKSOURCE_PLL RCC_CCIPR_CLK48SEL_1 /*!< PLL clock used as USB clock source */ +#define LL_RCC_USB_CLKSOURCE_MSI RCC_CCIPR_CLK48SEL /*!< MSI clock used as USB clock source */ +/** + * @} + */ + +#endif /* USB_OTG_FS || USB */ + +/** @defgroup RCC_LL_EC_ADC_CLKSOURCE Peripheral ADC clock source selection + * @{ + */ +#define LL_RCC_ADC_CLKSOURCE_NONE 0x00000000U /*!< No clock used as ADC clock source */ +#if defined(RCC_PLLSAI1_SUPPORT) +#define LL_RCC_ADC_CLKSOURCE_PLLSAI1 RCC_CCIPR_ADCSEL_0 /*!< PLLSAI1 clock used as ADC clock source */ +#endif /* RCC_PLLSAI1_SUPPORT */ +#if defined(RCC_PLLSAI2_SUPPORT) && !defined(LTDC) +#define LL_RCC_ADC_CLKSOURCE_PLLSAI2 RCC_CCIPR_ADCSEL_1 /*!< PLLSAI2 clock used as ADC clock source */ +#endif /* RCC_PLLSAI2_SUPPORT */ +#if defined(RCC_CCIPR_ADCSEL) +#define LL_RCC_ADC_CLKSOURCE_SYSCLK RCC_CCIPR_ADCSEL /*!< SYSCLK clock used as ADC clock source */ +#else +#define LL_RCC_ADC_CLKSOURCE_SYSCLK 0x30000000U /*!< SYSCLK clock used as ADC clock source */ +#endif +/** + * @} + */ + +#if defined(SWPMI1) +/** @defgroup RCC_LL_EC_SWPMI1_CLKSOURCE Peripheral SWPMI1 clock source selection + * @{ + */ +#define LL_RCC_SWPMI1_CLKSOURCE_PCLK1 0x00000000U /*!< PCLK1 used as SWPMI1 clock source */ +#define LL_RCC_SWPMI1_CLKSOURCE_HSI RCC_CCIPR_SWPMI1SEL /*!< HSI used as SWPMI1 clock source */ +/** + * @} + */ +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Channel0) +#if defined(RCC_CCIPR2_ADFSDM1SEL) +/** @defgroup RCC_LL_EC_DFSDM1_AUDIO_CLKSOURCE Peripheral DFSDM1 Audio clock source selection + * @{ + */ +#define LL_RCC_DFSDM1_AUDIO_CLKSOURCE_SAI1 0x00000000U /*!< SAI1 clock used as DFSDM1 Audio clock */ +#define LL_RCC_DFSDM1_AUDIO_CLKSOURCE_HSI RCC_CCIPR2_ADFSDM1SEL_0 /*!< HSI clock used as DFSDM1 Audio clock */ +#define LL_RCC_DFSDM1_AUDIO_CLKSOURCE_MSI RCC_CCIPR2_ADFSDM1SEL_1 /*!< MSI clock used as DFSDM1 Audio clock */ +/** + * @} + */ +#endif /* RCC_CCIPR2_ADFSDM1SEL */ + +/** @defgroup RCC_LL_EC_DFSDM1_CLKSOURCE Peripheral DFSDM1 clock source selection + * @{ + */ +#if defined(RCC_CCIPR2_DFSDM1SEL) +#define LL_RCC_DFSDM1_CLKSOURCE_PCLK2 0x00000000U /*!< PCLK2 used as DFSDM1 clock source */ +#define LL_RCC_DFSDM1_CLKSOURCE_SYSCLK RCC_CCIPR2_DFSDM1SEL /*!< SYSCLK used as DFSDM1 clock source */ +#else +#define LL_RCC_DFSDM1_CLKSOURCE_PCLK2 0x00000000U /*!< PCLK2 used as DFSDM1 clock source */ +#define LL_RCC_DFSDM1_CLKSOURCE_SYSCLK RCC_CCIPR_DFSDM1SEL /*!< SYSCLK used as DFSDM1 clock source */ +#endif /* RCC_CCIPR2_DFSDM1SEL */ +/** + * @} + */ +#endif /* DFSDM1_Channel0 */ + +#if defined(DSI) +/** @defgroup RCC_LL_EC_DSI_CLKSOURCE Peripheral DSI clock source selection + * @{ + */ +#define LL_RCC_DSI_CLKSOURCE_PHY 0x00000000U /*!< DSI-PHY clock used as DSI byte lane clock source */ +#define LL_RCC_DSI_CLKSOURCE_PLL RCC_CCIPR2_DSISEL /*!< PLL clock used as DSI byte lane clock source */ +/** + * @} + */ +#endif /* DSI */ + +#if defined(LTDC) +/** @defgroup RCC_LL_EC_LTDC_CLKSOURCE Peripheral LTDC clock source selection + * @{ + */ +#define LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV2 0x00000000U /*!< PLLSAI2DIVR divided by 2 used as LTDC clock source */ +#define LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV4 RCC_CCIPR2_PLLSAI2DIVR_0 /*!< PLLSAI2DIVR divided by 4 used as LTDC clock source */ +#define LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV8 RCC_CCIPR2_PLLSAI2DIVR_1 /*!< PLLSAI2DIVR divided by 8 used as LTDC clock source */ +#define LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV16 RCC_CCIPR2_PLLSAI2DIVR /*!< PLLSAI2DIVR divided by 16 used as LTDC clock source */ +/** + * @} + */ +#endif /* LTDC */ + +#if defined(OCTOSPI1) +/** @defgroup RCC_LL_EC_OCTOSPI Peripheral OCTOSPI get clock source + * @{ + */ +#define LL_RCC_OCTOSPI_CLKSOURCE_SYSCLK 0x00000000U /*!< SYSCLK used as OctoSPI clock source */ +#define LL_RCC_OCTOSPI_CLKSOURCE_MSI RCC_CCIPR2_OSPISEL_0 /*!< MSI used as OctoSPI clock source */ +#define LL_RCC_OCTOSPI_CLKSOURCE_PLL RCC_CCIPR2_OSPISEL_1 /*!< PLL used as OctoSPI clock source */ +/** + * @} + */ +#endif /* OCTOSPI1 */ + +/** @defgroup RCC_LL_EC_USART1 Peripheral USART get clock source + * @{ + */ +#define LL_RCC_USART1_CLKSOURCE RCC_CCIPR_USART1SEL /*!< USART1 Clock source selection */ +#define LL_RCC_USART2_CLKSOURCE RCC_CCIPR_USART2SEL /*!< USART2 Clock source selection */ +#if defined(RCC_CCIPR_USART3SEL) +#define LL_RCC_USART3_CLKSOURCE RCC_CCIPR_USART3SEL /*!< USART3 Clock source selection */ +#endif /* RCC_CCIPR_USART3SEL */ +/** + * @} + */ + +#if defined(RCC_CCIPR_UART4SEL) || defined(RCC_CCIPR_UART5SEL) +/** @defgroup RCC_LL_EC_UART4 Peripheral UART get clock source + * @{ + */ +#if defined(RCC_CCIPR_UART4SEL) +#define LL_RCC_UART4_CLKSOURCE RCC_CCIPR_UART4SEL /*!< UART4 Clock source selection */ +#endif /* RCC_CCIPR_UART4SEL */ +#if defined(RCC_CCIPR_UART5SEL) +#define LL_RCC_UART5_CLKSOURCE RCC_CCIPR_UART5SEL /*!< UART5 Clock source selection */ +#endif /* RCC_CCIPR_UART5SEL */ +/** + * @} + */ +#endif /* RCC_CCIPR_UART4SEL || RCC_CCIPR_UART5SEL */ + +/** @defgroup RCC_LL_EC_LPUART1 Peripheral LPUART get clock source + * @{ + */ +#define LL_RCC_LPUART1_CLKSOURCE RCC_CCIPR_LPUART1SEL /*!< LPUART1 Clock source selection */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_I2C1 Peripheral I2C get clock source + * @{ + */ +#define LL_RCC_I2C1_CLKSOURCE (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C1SEL_Pos << 16U) | (RCC_CCIPR_I2C1SEL >> RCC_CCIPR_I2C1SEL_Pos)) /*!< I2C1 Clock source selection */ +#if defined(RCC_CCIPR_I2C2SEL) +#define LL_RCC_I2C2_CLKSOURCE (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C2SEL_Pos << 16U) | (RCC_CCIPR_I2C2SEL >> RCC_CCIPR_I2C2SEL_Pos)) /*!< I2C2 Clock source selection */ +#endif /* RCC_CCIPR_I2C2SEL */ +#define LL_RCC_I2C3_CLKSOURCE (((uint32_t)RCC_OFFSET_CCIPR << 24U) | ((uint32_t)RCC_CCIPR_I2C3SEL_Pos << 16U) | (RCC_CCIPR_I2C3SEL >> RCC_CCIPR_I2C3SEL_Pos)) /*!< I2C3 Clock source selection */ +#if defined(RCC_CCIPR2_I2C4SEL) +#define LL_RCC_I2C4_CLKSOURCE (((uint32_t)RCC_OFFSET_CCIPR2 << 24U) | ((uint32_t)RCC_CCIPR2_I2C4SEL_Pos << 16U) | (RCC_CCIPR2_I2C4SEL >> RCC_CCIPR2_I2C4SEL_Pos)) /*!< I2C4 Clock source selection */ +#endif /* RCC_CCIPR2_I2C4SEL */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_LPTIM1 Peripheral LPTIM get clock source + * @{ + */ +#define LL_RCC_LPTIM1_CLKSOURCE RCC_CCIPR_LPTIM1SEL /*!< LPTIM1 Clock source selection */ +#define LL_RCC_LPTIM2_CLKSOURCE RCC_CCIPR_LPTIM2SEL /*!< LPTIM2 Clock source selection */ +/** + * @} + */ + +#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR2_SAI1SEL) +/** @defgroup RCC_LL_EC_SAI1 Peripheral SAI get clock source + * @{ + */ +#if defined(RCC_CCIPR2_SAI1SEL) +#define LL_RCC_SAI1_CLKSOURCE RCC_CCIPR2_SAI1SEL /*!< SAI1 Clock source selection */ +#else +#define LL_RCC_SAI1_CLKSOURCE RCC_CCIPR_SAI1SEL /*!< SAI1 Clock source selection */ +#endif /* RCC_CCIPR2_SAI1SEL */ +#if defined(RCC_CCIPR2_SAI2SEL) +#define LL_RCC_SAI2_CLKSOURCE RCC_CCIPR2_SAI2SEL /*!< SAI2 Clock source selection */ +#elif defined(RCC_CCIPR_SAI2SEL) +#define LL_RCC_SAI2_CLKSOURCE RCC_CCIPR_SAI2SEL /*!< SAI2 Clock source selection */ +#endif /* RCC_CCIPR2_SAI2SEL */ +/** + * @} + */ +#endif /* RCC_CCIPR_SAI1SEL || RCC_CCIPR2_SAI1SEL */ + +#if defined(SDMMC1) +#if defined(RCC_CCIPR2_SDMMCSEL) +/** @defgroup RCC_LL_EC_SDMMC1_KERNEL Peripheral SDMMC get kernel clock source + * @{ + */ +#define LL_RCC_SDMMC1_KERNELCLKSOURCE RCC_CCIPR2_SDMMCSEL /*!< SDMMC1 Kernel Clock source selection */ +/** + * @} + */ +#endif /* RCC_CCIPR2_SDMMCSEL */ + +/** @defgroup RCC_LL_EC_SDMMC1 Peripheral SDMMC get clock source + * @{ + */ +#define LL_RCC_SDMMC1_CLKSOURCE RCC_CCIPR_CLK48SEL /*!< SDMMC1 Clock source selection */ +/** + * @} + */ +#endif /* SDMMC1 */ + +/** @defgroup RCC_LL_EC_RNG Peripheral RNG get clock source + * @{ + */ +#define LL_RCC_RNG_CLKSOURCE RCC_CCIPR_CLK48SEL /*!< RNG Clock source selection */ +/** + * @} + */ + +#if defined(USB_OTG_FS) || defined(USB) +/** @defgroup RCC_LL_EC_USB Peripheral USB get clock source + * @{ + */ +#define LL_RCC_USB_CLKSOURCE RCC_CCIPR_CLK48SEL /*!< USB Clock source selection */ +/** + * @} + */ +#endif /* USB_OTG_FS || USB */ + +/** @defgroup RCC_LL_EC_ADC Peripheral ADC get clock source + * @{ + */ +#if defined(RCC_CCIPR_ADCSEL) +#define LL_RCC_ADC_CLKSOURCE RCC_CCIPR_ADCSEL /*!< ADC Clock source selection */ +#else +#define LL_RCC_ADC_CLKSOURCE 0x30000000U /*!< ADC Clock source selection */ +#endif +/** + * @} + */ + +#if defined(SWPMI1) +/** @defgroup RCC_LL_EC_SWPMI1 Peripheral SWPMI1 get clock source + * @{ + */ +#define LL_RCC_SWPMI1_CLKSOURCE RCC_CCIPR_SWPMI1SEL /*!< SWPMI1 Clock source selection */ +/** + * @} + */ +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Channel0) +#if defined(RCC_CCIPR2_ADFSDM1SEL) +/** @defgroup RCC_LL_EC_DFSDM1_AUDIO Peripheral DFSDM1 Audio get clock source + * @{ + */ +#define LL_RCC_DFSDM1_AUDIO_CLKSOURCE RCC_CCIPR2_ADFSDM1SEL /* DFSDM1 Audio Clock source selection */ +/** + * @} + */ + +#endif /* RCC_CCIPR2_ADFSDM1SEL */ +/** @defgroup RCC_LL_EC_DFSDM1 Peripheral DFSDM1 get clock source + * @{ + */ +#if defined(RCC_CCIPR2_DFSDM1SEL) +#define LL_RCC_DFSDM1_CLKSOURCE RCC_CCIPR2_DFSDM1SEL /*!< DFSDM1 Clock source selection */ +#else +#define LL_RCC_DFSDM1_CLKSOURCE RCC_CCIPR_DFSDM1SEL /*!< DFSDM1 Clock source selection */ +#endif /* RCC_CCIPR2_DFSDM1SEL */ +/** + * @} + */ +#endif /* DFSDM1_Channel0 */ + +#if defined(DSI) +/** @defgroup RCC_LL_EC_DSI Peripheral DSI get clock source + * @{ + */ +#define LL_RCC_DSI_CLKSOURCE RCC_CCIPR2_DSISEL /*!< DSI Clock source selection */ +/** + * @} + */ +#endif /* DSI */ + +#if defined(LTDC) +/** @defgroup RCC_LL_EC_LTDC Peripheral LTDC get clock source + * @{ + */ +#define LL_RCC_LTDC_CLKSOURCE RCC_CCIPR2_PLLSAI2DIVR /*!< LTDC Clock source selection */ +/** + * @} + */ +#endif /* LTDC */ + +#if defined(OCTOSPI1) +/** @defgroup RCC_LL_EC_OCTOSPI Peripheral OCTOSPI get clock source + * @{ + */ +#define LL_RCC_OCTOSPI_CLKSOURCE RCC_CCIPR2_OSPISEL /*!< OctoSPI Clock source selection */ +/** + * @} + */ +#endif /* OCTOSPI1 */ + + +/** @defgroup RCC_LL_EC_RTC_CLKSOURCE RTC clock source selection + * @{ + */ +#define LL_RCC_RTC_CLKSOURCE_NONE 0x00000000U /*!< No clock used as RTC clock */ +#define LL_RCC_RTC_CLKSOURCE_LSE RCC_BDCR_RTCSEL_0 /*!< LSE oscillator clock used as RTC clock */ +#define LL_RCC_RTC_CLKSOURCE_LSI RCC_BDCR_RTCSEL_1 /*!< LSI oscillator clock used as RTC clock */ +#define LL_RCC_RTC_CLKSOURCE_HSE_DIV32 RCC_BDCR_RTCSEL /*!< HSE oscillator clock divided by 32 used as RTC clock */ +/** + * @} + */ + + +/** @defgroup RCC_LL_EC_PLLSOURCE PLL, PLLSAI1 and PLLSAI2 entry clock source + * @{ + */ +#define LL_RCC_PLLSOURCE_NONE 0x00000000U /*!< No clock */ +#define LL_RCC_PLLSOURCE_MSI RCC_PLLCFGR_PLLSRC_MSI /*!< MSI clock selected as PLL entry clock source */ +#define LL_RCC_PLLSOURCE_HSI RCC_PLLCFGR_PLLSRC_HSI /*!< HSI16 clock selected as PLL entry clock source */ +#define LL_RCC_PLLSOURCE_HSE RCC_PLLCFGR_PLLSRC_HSE /*!< HSE clock selected as PLL entry clock source */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_PLLM_DIV PLL division factor + * @{ + */ +#define LL_RCC_PLLM_DIV_1 0x00000000U /*!< Main PLL division factor for PLLM input by 1 */ +#define LL_RCC_PLLM_DIV_2 (RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 2 */ +#define LL_RCC_PLLM_DIV_3 (RCC_PLLCFGR_PLLM_1) /*!< Main PLL division factor for PLLM input by 3 */ +#define LL_RCC_PLLM_DIV_4 (RCC_PLLCFGR_PLLM_1 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 4 */ +#define LL_RCC_PLLM_DIV_5 (RCC_PLLCFGR_PLLM_2) /*!< Main PLL division factor for PLLM input by 5 */ +#define LL_RCC_PLLM_DIV_6 (RCC_PLLCFGR_PLLM_2 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 6 */ +#define LL_RCC_PLLM_DIV_7 (RCC_PLLCFGR_PLLM_2 | RCC_PLLCFGR_PLLM_1) /*!< Main PLL division factor for PLLM input by 7 */ +#define LL_RCC_PLLM_DIV_8 (RCC_PLLCFGR_PLLM_2 | RCC_PLLCFGR_PLLM_1 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 8 */ +#if defined(RCC_PLLM_DIV_1_16_SUPPORT) +#define LL_RCC_PLLM_DIV_9 (RCC_PLLCFGR_PLLM_3) /*!< Main PLL division factor for PLLM input by 9 */ +#define LL_RCC_PLLM_DIV_10 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 10 */ +#define LL_RCC_PLLM_DIV_11 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_1) /*!< Main PLL division factor for PLLM input by 11 */ +#define LL_RCC_PLLM_DIV_12 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_1 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 12 */ +#define LL_RCC_PLLM_DIV_13 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_2) /*!< Main PLL division factor for PLLM input by 13 */ +#define LL_RCC_PLLM_DIV_14 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_2 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 14 */ +#define LL_RCC_PLLM_DIV_15 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_2 | RCC_PLLCFGR_PLLM_1) /*!< Main PLL division factor for PLLM input by 15 */ +#define LL_RCC_PLLM_DIV_16 (RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLM_2 | RCC_PLLCFGR_PLLM_1 | RCC_PLLCFGR_PLLM_0) /*!< Main PLL division factor for PLLM input by 16 */ +#endif /* RCC_PLLM_DIV_1_16_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_PLLR_DIV PLL division factor (PLLR) + * @{ + */ +#define LL_RCC_PLLR_DIV_2 0x00000000U /*!< Main PLL division factor for PLLCLK (system clock) by 2 */ +#define LL_RCC_PLLR_DIV_4 (RCC_PLLCFGR_PLLR_0) /*!< Main PLL division factor for PLLCLK (system clock) by 4 */ +#define LL_RCC_PLLR_DIV_6 (RCC_PLLCFGR_PLLR_1) /*!< Main PLL division factor for PLLCLK (system clock) by 6 */ +#define LL_RCC_PLLR_DIV_8 (RCC_PLLCFGR_PLLR) /*!< Main PLL division factor for PLLCLK (system clock) by 8 */ +/** + * @} + */ + +#if defined(RCC_PLLP_SUPPORT) +/** @defgroup RCC_LL_EC_PLLP_DIV PLL division factor (PLLP) + * @{ + */ +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +#define LL_RCC_PLLP_DIV_2 (RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 2 */ +#define LL_RCC_PLLP_DIV_3 (RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 3 */ +#define LL_RCC_PLLP_DIV_4 (RCC_PLLCFGR_PLLPDIV_2) /*!< Main PLL division factor for PLLP output by 4 */ +#define LL_RCC_PLLP_DIV_5 (RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 5 */ +#define LL_RCC_PLLP_DIV_6 (RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 6 */ +#define LL_RCC_PLLP_DIV_7 (RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 7 */ +#define LL_RCC_PLLP_DIV_8 (RCC_PLLCFGR_PLLPDIV_3) /*!< Main PLL division factor for PLLP output by 8 */ +#define LL_RCC_PLLP_DIV_9 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 9 */ +#define LL_RCC_PLLP_DIV_10 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 10 */ +#define LL_RCC_PLLP_DIV_11 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 11 */ +#define LL_RCC_PLLP_DIV_12 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2) /*!< Main PLL division factor for PLLP output by 12 */ +#define LL_RCC_PLLP_DIV_13 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 13 */ +#define LL_RCC_PLLP_DIV_14 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 14 */ +#define LL_RCC_PLLP_DIV_15 (RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 15 */ +#define LL_RCC_PLLP_DIV_16 (RCC_PLLCFGR_PLLPDIV_4) /*!< Main PLL division factor for PLLP output by 16 */ +#define LL_RCC_PLLP_DIV_17 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 17 */ +#define LL_RCC_PLLP_DIV_18 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 18 */ +#define LL_RCC_PLLP_DIV_19 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 19 */ +#define LL_RCC_PLLP_DIV_20 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_2) /*!< Main PLL division factor for PLLP output by 20 */ +#define LL_RCC_PLLP_DIV_21 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 21 */ +#define LL_RCC_PLLP_DIV_22 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 22 */ +#define LL_RCC_PLLP_DIV_23 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 23 */ +#define LL_RCC_PLLP_DIV_24 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3) /*!< Main PLL division factor for PLLP output by 24 */ +#define LL_RCC_PLLP_DIV_25 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 25 */ +#define LL_RCC_PLLP_DIV_26 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 26 */ +#define LL_RCC_PLLP_DIV_27 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 27 */ +#define LL_RCC_PLLP_DIV_28 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2) /*!< Main PLL division factor for PLLP output by 28 */ +#define LL_RCC_PLLP_DIV_29 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 29 */ +#define LL_RCC_PLLP_DIV_30 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1) /*!< Main PLL division factor for PLLP output by 30 */ +#define LL_RCC_PLLP_DIV_31 (RCC_PLLCFGR_PLLPDIV_4|RCC_PLLCFGR_PLLPDIV_3|RCC_PLLCFGR_PLLPDIV_2|RCC_PLLCFGR_PLLPDIV_1|RCC_PLLCFGR_PLLPDIV_0) /*!< Main PLL division factor for PLLP output by 31 */ +#else +#define LL_RCC_PLLP_DIV_7 0x00000000U /*!< Main PLL division factor for PLLP output by 7 */ +#define LL_RCC_PLLP_DIV_17 (RCC_PLLCFGR_PLLP) /*!< Main PLL division factor for PLLP output by 17 */ +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +/** + * @} + */ +#endif /* RCC_PLLP_SUPPORT */ + +/** @defgroup RCC_LL_EC_PLLQ_DIV PLL division factor (PLLQ) + * @{ + */ +#define LL_RCC_PLLQ_DIV_2 0x00000000U /*!< Main PLL division factor for PLLQ output by 2 */ +#define LL_RCC_PLLQ_DIV_4 (RCC_PLLCFGR_PLLQ_0) /*!< Main PLL division factor for PLLQ output by 4 */ +#define LL_RCC_PLLQ_DIV_6 (RCC_PLLCFGR_PLLQ_1) /*!< Main PLL division factor for PLLQ output by 6 */ +#define LL_RCC_PLLQ_DIV_8 (RCC_PLLCFGR_PLLQ) /*!< Main PLL division factor for PLLQ output by 8 */ +/** + * @} + */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +/** @defgroup RCC_LL_EC_PLLSAI1M PLLSAI1 division factor (PLLSAI1M) + * @{ + */ +#define LL_RCC_PLLSAI1M_DIV_1 0x00000000U /*!< PLLSAI1 division factor for PLLSAI1M input by 1 */ +#define LL_RCC_PLLSAI1M_DIV_2 (RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 2 */ +#define LL_RCC_PLLSAI1M_DIV_3 (RCC_PLLSAI1CFGR_PLLSAI1M_1) /*!< PLLSAI1 division factor for PLLSAI1M input by 3 */ +#define LL_RCC_PLLSAI1M_DIV_4 (RCC_PLLSAI1CFGR_PLLSAI1M_1|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 4 */ +#define LL_RCC_PLLSAI1M_DIV_5 (RCC_PLLSAI1CFGR_PLLSAI1M_2) /*!< PLLSAI1 division factor for PLLSAI1M input by 5 */ +#define LL_RCC_PLLSAI1M_DIV_6 (RCC_PLLSAI1CFGR_PLLSAI1M_2|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 6 */ +#define LL_RCC_PLLSAI1M_DIV_7 (RCC_PLLSAI1CFGR_PLLSAI1M_2|RCC_PLLSAI1CFGR_PLLSAI1M_1) /*!< PLLSAI1 division factor for PLLSAI1M input by 7 */ +#define LL_RCC_PLLSAI1M_DIV_8 (RCC_PLLSAI1CFGR_PLLSAI1M_2|RCC_PLLSAI1CFGR_PLLSAI1M_1|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 8 */ +#define LL_RCC_PLLSAI1M_DIV_9 (RCC_PLLSAI1CFGR_PLLSAI1M_3) /*!< PLLSAI1 division factor for PLLSAI1M input by 9 */ +#define LL_RCC_PLLSAI1M_DIV_10 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 10 */ +#define LL_RCC_PLLSAI1M_DIV_11 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_1) /*!< PLLSAI1 division factor for PLLSAI1M input by 11 */ +#define LL_RCC_PLLSAI1M_DIV_12 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_1|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 12 */ +#define LL_RCC_PLLSAI1M_DIV_13 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_2) /*!< PLLSAI1 division factor for PLLSAI1M input by 13 */ +#define LL_RCC_PLLSAI1M_DIV_14 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_2|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 14 */ +#define LL_RCC_PLLSAI1M_DIV_15 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_2|RCC_PLLSAI1CFGR_PLLSAI1M_1) /*!< PLLSAI1 division factor for PLLSAI1M input by 15 */ +#define LL_RCC_PLLSAI1M_DIV_16 (RCC_PLLSAI1CFGR_PLLSAI1M_3|RCC_PLLSAI1CFGR_PLLSAI1M_2|RCC_PLLSAI1CFGR_PLLSAI1M_1|RCC_PLLSAI1CFGR_PLLSAI1M_0) /*!< PLLSAI1 division factor for PLLSAI1M input by 16 */ +/** + * @} + */ +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** @defgroup RCC_LL_EC_PLLSAI1Q PLLSAI1 division factor (PLLSAI1Q) + * @{ + */ +#define LL_RCC_PLLSAI1Q_DIV_2 0x00000000U /*!< PLLSAI1 division factor for PLLSAI1Q output by 2 */ +#define LL_RCC_PLLSAI1Q_DIV_4 (RCC_PLLSAI1CFGR_PLLSAI1Q_0) /*!< PLLSAI1 division factor for PLLSAI1Q output by 4 */ +#define LL_RCC_PLLSAI1Q_DIV_6 (RCC_PLLSAI1CFGR_PLLSAI1Q_1) /*!< PLLSAI1 division factor for PLLSAI1Q output by 6 */ +#define LL_RCC_PLLSAI1Q_DIV_8 (RCC_PLLSAI1CFGR_PLLSAI1Q) /*!< PLLSAI1 division factor for PLLSAI1Q output by 8 */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_PLLSAI1P PLLSAI1 division factor (PLLSAI1P) + * @{ + */ +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +#define LL_RCC_PLLSAI1P_DIV_2 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 2 */ +#define LL_RCC_PLLSAI1P_DIV_3 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 3 */ +#define LL_RCC_PLLSAI1P_DIV_4 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_2) /*!< PLLSAI1 division factor for PLLSAI1P output by 4 */ +#define LL_RCC_PLLSAI1P_DIV_5 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 5 */ +#define LL_RCC_PLLSAI1P_DIV_6 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 6 */ +#define LL_RCC_PLLSAI1P_DIV_7 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 7 */ +#define LL_RCC_PLLSAI1P_DIV_8 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3) /*!< PLLSAI1 division factor for PLLSAI1P output by 8 */ +#define LL_RCC_PLLSAI1P_DIV_9 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 9 */ +#define LL_RCC_PLLSAI1P_DIV_10 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 10 */ +#define LL_RCC_PLLSAI1P_DIV_11 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 1 */ +#define LL_RCC_PLLSAI1P_DIV_12 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2) /*!< PLLSAI1 division factor for PLLSAI1P output by 12 */ +#define LL_RCC_PLLSAI1P_DIV_13 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 13 */ +#define LL_RCC_PLLSAI1P_DIV_14 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 14 */ +#define LL_RCC_PLLSAI1P_DIV_15 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 15 */ +#define LL_RCC_PLLSAI1P_DIV_16 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4) /*!< PLLSAI1 division factor for PLLSAI1P output by 16 */ +#define LL_RCC_PLLSAI1P_DIV_17 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 17 */ +#define LL_RCC_PLLSAI1P_DIV_18 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 18 */ +#define LL_RCC_PLLSAI1P_DIV_19 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 19 */ +#define LL_RCC_PLLSAI1P_DIV_20 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2) /*!< PLLSAI1 division factor for PLLSAI1P output by 20 */ +#define LL_RCC_PLLSAI1P_DIV_21 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division fctor for PLLSAI1P output by 21 */ +#define LL_RCC_PLLSAI1P_DIV_22 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 22 */ +#define LL_RCC_PLLSAI1P_DIV_23 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 23 */ +#define LL_RCC_PLLSAI1P_DIV_24 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3) /*!< PLLSAI1 division factor for PLLSAI1P output by 24 */ +#define LL_RCC_PLLSAI1P_DIV_25 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 25 */ +#define LL_RCC_PLLSAI1P_DIV_26 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 26 */ +#define LL_RCC_PLLSAI1P_DIV_27 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 27 */ +#define LL_RCC_PLLSAI1P_DIV_28 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2) /*!< PLLSAI1 division factor for PLLSAI1P output by 28 */ +#define LL_RCC_PLLSAI1P_DIV_29 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 29 */ +#define LL_RCC_PLLSAI1P_DIV_30 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1) /*!< PLLSAI1 division factor for PLLSAI1P output by 30 */ +#define LL_RCC_PLLSAI1P_DIV_31 (RCC_PLLSAI1CFGR_PLLSAI1PDIV_4|RCC_PLLSAI1CFGR_PLLSAI1PDIV_3|RCC_PLLSAI1CFGR_PLLSAI1PDIV_2|RCC_PLLSAI1CFGR_PLLSAI1PDIV_1|RCC_PLLSAI1CFGR_PLLSAI1PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 31 */ +#else +#define LL_RCC_PLLSAI1P_DIV_7 0x00000000U /*!< PLLSAI1 division factor for PLLSAI1P output by 7 */ +#define LL_RCC_PLLSAI1P_DIV_17 (RCC_PLLSAI1CFGR_PLLSAI1P) /*!< PLLSAI1 division factor for PLLSAI1P output by 17 */ +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_PLLSAI1R PLLSAI1 division factor (PLLSAI1R) + * @{ + */ +#define LL_RCC_PLLSAI1R_DIV_2 0x00000000U /*!< PLLSAI1 division factor for PLLSAI1R output by 2 */ +#define LL_RCC_PLLSAI1R_DIV_4 (RCC_PLLSAI1CFGR_PLLSAI1R_0) /*!< PLLSAI1 division factor for PLLSAI1R output by 4 */ +#define LL_RCC_PLLSAI1R_DIV_6 (RCC_PLLSAI1CFGR_PLLSAI1R_1) /*!< PLLSAI1 division factor for PLLSAI1R output by 6 */ +#define LL_RCC_PLLSAI1R_DIV_8 (RCC_PLLSAI1CFGR_PLLSAI1R) /*!< PLLSAI1 division factor for PLLSAI1R output by 8 */ +/** + * @} + */ +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) +/** @defgroup RCC_LL_EC_PLLSAI2M PLLSAI1 division factor (PLLSAI2M) + * @{ + */ +#define LL_RCC_PLLSAI2M_DIV_1 0x00000000U /*!< PLLSAI2 division factor for PLLSAI2M input by 1 */ +#define LL_RCC_PLLSAI2M_DIV_2 (RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 2 */ +#define LL_RCC_PLLSAI2M_DIV_3 (RCC_PLLSAI2CFGR_PLLSAI2M_1) /*!< PLLSAI2 division factor for PLLSAI2M input by 3 */ +#define LL_RCC_PLLSAI2M_DIV_4 (RCC_PLLSAI2CFGR_PLLSAI2M_1|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 4 */ +#define LL_RCC_PLLSAI2M_DIV_5 (RCC_PLLSAI2CFGR_PLLSAI2M_2) /*!< PLLSAI2 division factor for PLLSAI2M input by 5 */ +#define LL_RCC_PLLSAI2M_DIV_6 (RCC_PLLSAI2CFGR_PLLSAI2M_2|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 6 */ +#define LL_RCC_PLLSAI2M_DIV_7 (RCC_PLLSAI2CFGR_PLLSAI2M_2|RCC_PLLSAI2CFGR_PLLSAI2M_1) /*!< PLLSAI2 division factor for PLLSAI2M input by 7 */ +#define LL_RCC_PLLSAI2M_DIV_8 (RCC_PLLSAI2CFGR_PLLSAI2M_2|RCC_PLLSAI2CFGR_PLLSAI2M_1|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 8 */ +#define LL_RCC_PLLSAI2M_DIV_9 (RCC_PLLSAI2CFGR_PLLSAI2M_3) /*!< PLLSAI2 division factor for PLLSAI2M input by 9 */ +#define LL_RCC_PLLSAI2M_DIV_10 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 10 */ +#define LL_RCC_PLLSAI2M_DIV_11 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_1) /*!< PLLSAI2 division factor for PLLSAI2M input by 11 */ +#define LL_RCC_PLLSAI2M_DIV_12 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_1|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 12 */ +#define LL_RCC_PLLSAI2M_DIV_13 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_2) /*!< PLLSAI2 division factor for PLLSAI2M input by 13 */ +#define LL_RCC_PLLSAI2M_DIV_14 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_2|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 14 */ +#define LL_RCC_PLLSAI2M_DIV_15 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_2|RCC_PLLSAI2CFGR_PLLSAI2M_1) /*!< PLLSAI2 division factor for PLLSAI2M input by 15 */ +#define LL_RCC_PLLSAI2M_DIV_16 (RCC_PLLSAI2CFGR_PLLSAI2M_3|RCC_PLLSAI2CFGR_PLLSAI2M_2|RCC_PLLSAI2CFGR_PLLSAI2M_1|RCC_PLLSAI2CFGR_PLLSAI2M_0) /*!< PLLSAI2 division factor for PLLSAI2M input by 16 */ +/** + * @} + */ +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) +/** @defgroup RCC_LL_EC_PLLSAI2Q PLLSAI2 division factor (PLLSAI2Q) + * @{ + */ +#define LL_RCC_PLLSAI2Q_DIV_2 0x00000000U /*!< PLLSAI2 division factor for PLLSAI2Q output by 2 */ +#define LL_RCC_PLLSAI2Q_DIV_4 (RCC_PLLSAI2CFGR_PLLSAI2Q_0) /*!< PLLSAI2 division factor for PLLSAI2Q output by 4 */ +#define LL_RCC_PLLSAI2Q_DIV_6 (RCC_PLLSAI2CFGR_PLLSAI2Q_1) /*!< PLLSAI2 division factor for PLLSAI2Q output by 6 */ +#define LL_RCC_PLLSAI2Q_DIV_8 (RCC_PLLSAI2CFGR_PLLSAI2Q) /*!< PLLSAI2 division factor for PLLSAI2Q output by 8 */ +/** + * @} + */ +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + +/** @defgroup RCC_LL_EC_PLLSAI2P PLLSAI2 division factor (PLLSAI2P) + * @{ + */ +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +#define LL_RCC_PLLSAI2P_DIV_2 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 2 */ +#define LL_RCC_PLLSAI2P_DIV_3 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 3 */ +#define LL_RCC_PLLSAI2P_DIV_4 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_2) /*!< PLLSAI2 division factor for PLLSAI2P output by 4 */ +#define LL_RCC_PLLSAI2P_DIV_5 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 5 */ +#define LL_RCC_PLLSAI2P_DIV_6 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 6 */ +#define LL_RCC_PLLSAI2P_DIV_7 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 7 */ +#define LL_RCC_PLLSAI2P_DIV_8 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3) /*!< PLLSAI2 division factor for PLLSAI2P output by 8 */ +#define LL_RCC_PLLSAI2P_DIV_9 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 9 */ +#define LL_RCC_PLLSAI2P_DIV_10 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 10 */ +#define LL_RCC_PLLSAI2P_DIV_11 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 1 */ +#define LL_RCC_PLLSAI2P_DIV_12 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2) /*!< PLLSAI2 division factor for PLLSAI2P output by 12 */ +#define LL_RCC_PLLSAI2P_DIV_13 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 13 */ +#define LL_RCC_PLLSAI2P_DIV_14 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 14 */ +#define LL_RCC_PLLSAI2P_DIV_15 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 15 */ +#define LL_RCC_PLLSAI2P_DIV_16 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4) /*!< PLLSAI2 division factor for PLLSAI2P output by 16 */ +#define LL_RCC_PLLSAI2P_DIV_17 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 17 */ +#define LL_RCC_PLLSAI2P_DIV_18 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 18 */ +#define LL_RCC_PLLSAI2P_DIV_19 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 19 */ +#define LL_RCC_PLLSAI2P_DIV_20 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2) /*!< PLLSAI2 division factor for PLLSAI2P output by 20 */ +#define LL_RCC_PLLSAI2P_DIV_21 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division fctor for PLLSAI2P output by 21 */ +#define LL_RCC_PLLSAI2P_DIV_22 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 22 */ +#define LL_RCC_PLLSAI2P_DIV_23 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 23 */ +#define LL_RCC_PLLSAI2P_DIV_24 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3) /*!< PLLSAI2 division factor for PLLSAI2P output by 24 */ +#define LL_RCC_PLLSAI2P_DIV_25 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 25 */ +#define LL_RCC_PLLSAI2P_DIV_26 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 26 */ +#define LL_RCC_PLLSAI2P_DIV_27 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 27 */ +#define LL_RCC_PLLSAI2P_DIV_28 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2) /*!< PLLSAI2 division factor for PLLSAI2P output by 28 */ +#define LL_RCC_PLLSAI2P_DIV_29 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI2 division factor for PLLSAI2P output by 29 */ +#define LL_RCC_PLLSAI2P_DIV_30 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1) /*!< PLLSAI2 division factor for PLLSAI2P output by 30 */ +#define LL_RCC_PLLSAI2P_DIV_31 (RCC_PLLSAI2CFGR_PLLSAI2PDIV_4|RCC_PLLSAI2CFGR_PLLSAI2PDIV_3|RCC_PLLSAI2CFGR_PLLSAI2PDIV_2|RCC_PLLSAI2CFGR_PLLSAI2PDIV_1|RCC_PLLSAI2CFGR_PLLSAI2PDIV_0) /*!< PLLSAI1 division factor for PLLSAI1P output by 31 */ +#else +#define LL_RCC_PLLSAI2P_DIV_7 0x00000000U /*!< PLLSAI2 division factor for PLLSAI2P output by 7 */ +#define LL_RCC_PLLSAI2P_DIV_17 (RCC_PLLSAI2CFGR_PLLSAI2P) /*!< PLLSAI2 division factor for PLLSAI2P output by 17 */ +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ +/** + * @} + */ + +/** @defgroup RCC_LL_EC_PLLSAI2R PLLSAI2 division factor (PLLSAI2R) + * @{ + */ +#define LL_RCC_PLLSAI2R_DIV_2 0x00000000U /*!< PLLSAI2 division factor for PLLSAI2R output by 2 */ +#define LL_RCC_PLLSAI2R_DIV_4 (RCC_PLLSAI2CFGR_PLLSAI2R_0) /*!< PLLSAI2 division factor for PLLSAI2R output by 4 */ +#define LL_RCC_PLLSAI2R_DIV_6 (RCC_PLLSAI2CFGR_PLLSAI2R_1) /*!< PLLSAI2 division factor for PLLSAI2R output by 6 */ +#define LL_RCC_PLLSAI2R_DIV_8 (RCC_PLLSAI2CFGR_PLLSAI2R) /*!< PLLSAI2 division factor for PLLSAI2R output by 8 */ +/** + * @} + */ + +#if defined(RCC_CCIPR2_PLLSAI2DIVR) +/** @defgroup RCC_LL_EC_PLLSAI2DIVR PLLSAI2DIVR division factor (PLLSAI2DIVR) + * @{ + */ +#define LL_RCC_PLLSAI2DIVR_DIV_2 0x00000000U /*!< PLLSAI2 division factor for PLLSAI2DIVR output by 2 */ +#define LL_RCC_PLLSAI2DIVR_DIV_4 RCC_CCIPR2_PLLSAI2DIVR_0 /*!< PLLSAI2 division factor for PLLSAI2DIVR output by 4 */ +#define LL_RCC_PLLSAI2DIVR_DIV_8 RCC_CCIPR2_PLLSAI2DIVR_1 /*!< PLLSAI2 division factor for PLLSAI2DIVR output by 8 */ +#define LL_RCC_PLLSAI2DIVR_DIV_16 (RCC_CCIPR2_PLLSAI2DIVR_1 | RCC_CCIPR2_PLLSAI2DIVR_0) /*!< PLLSAI2 division factor for PLLSAI2DIVR output by 16 */ +/** + * @} + */ +#endif /* RCC_CCIPR2_PLLSAI2DIVR */ +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** @defgroup RCC_LL_EC_MSIRANGESEL MSI clock range selection + * @{ + */ +#define LL_RCC_MSIRANGESEL_STANDBY 0U /*!< MSI Range is provided by MSISRANGE */ +#define LL_RCC_MSIRANGESEL_RUN 1U /*!< MSI Range is provided by MSIRANGE */ +/** + * @} + */ + +#if defined(RCC_CSR_LSIPREDIV) +/** @defgroup RCC_LL_EC_LSIPREDIV LSI division factor + * @{ + */ +#define LL_RCC_LSI_PREDIV_1 0x00000000U /*!< LSI division factor by 1 */ +#define LL_RCC_LSI_PREDIV_128 RCC_CSR_LSIPREDIV /*!< LSI division factor by 128 */ +/** + * @} + */ +#endif /* RCC_CSR_LSIPREDIV */ + +/** Legacy definitions for compatibility purpose +@cond 0 +*/ +#if defined(DFSDM1_Channel0) +#define LL_RCC_DFSDM1_CLKSOURCE_PCLK LL_RCC_DFSDM1_CLKSOURCE_PCLK2 +#define LL_RCC_DFSDM_CLKSOURCE_PCLK LL_RCC_DFSDM1_CLKSOURCE_PCLK2 +#define LL_RCC_DFSDM_CLKSOURCE_SYSCLK LL_RCC_DFSDM1_CLKSOURCE_SYSCLK +#define LL_RCC_DFSDM_CLKSOURCE LL_RCC_DFSDM1_CLKSOURCE +#endif /* DFSDM1_Channel0 */ +#if defined(SWPMI1) +#define LL_RCC_SWPMI1_CLKSOURCE_PCLK LL_RCC_SWPMI1_CLKSOURCE_PCLK1 +#endif /* SWPMI1 */ +/** +@endcond + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup RCC_LL_Exported_Macros RCC Exported Macros + * @{ + */ + +/** @defgroup RCC_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in RCC register + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_RCC_WriteReg(__REG__, __VALUE__) WRITE_REG(RCC->__REG__, (__VALUE__)) + +/** + * @brief Read a value in RCC register + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_RCC_ReadReg(__REG__) READ_REG(RCC->__REG__) +/** + * @} + */ + +/** @defgroup RCC_LL_EM_CALC_FREQ Calculate frequencies + * @{ + */ + +/** + * @brief Helper macro to calculate the PLLCLK frequency on system domain + * @note ex: @ref __LL_RCC_CALC_PLLCLK_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLL_GetN (), @ref LL_RCC_PLL_GetR ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + * @param __PLLN__ Between 8 and 86 or 127 depending on devices + * @param __PLLR__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLR_DIV_2 + * @arg @ref LL_RCC_PLLR_DIV_4 + * @arg @ref LL_RCC_PLLR_DIV_6 + * @arg @ref LL_RCC_PLLR_DIV_8 + * @retval PLL clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLCLK_FREQ(__INPUTFREQ__, __PLLM__, __PLLN__, __PLLR__) ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLN__) / \ + ((((__PLLR__) >> RCC_PLLCFGR_PLLR_Pos) + 1U) * 2U)) + +#if defined(RCC_PLLSAI1_SUPPORT) +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +/** + * @brief Helper macro to calculate the PLLCLK frequency used on SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLCLK_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLL_GetN (), @ref LL_RCC_PLL_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + * @param __PLLN__ Between 8 and 86 or 127 depending on devices + * @param __PLLP__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLP_DIV_2 + * @arg @ref LL_RCC_PLLP_DIV_3 + * @arg @ref LL_RCC_PLLP_DIV_4 + * @arg @ref LL_RCC_PLLP_DIV_5 + * @arg @ref LL_RCC_PLLP_DIV_6 + * @arg @ref LL_RCC_PLLP_DIV_7 + * @arg @ref LL_RCC_PLLP_DIV_8 + * @arg @ref LL_RCC_PLLP_DIV_9 + * @arg @ref LL_RCC_PLLP_DIV_10 + * @arg @ref LL_RCC_PLLP_DIV_11 + * @arg @ref LL_RCC_PLLP_DIV_12 + * @arg @ref LL_RCC_PLLP_DIV_13 + * @arg @ref LL_RCC_PLLP_DIV_14 + * @arg @ref LL_RCC_PLLP_DIV_15 + * @arg @ref LL_RCC_PLLP_DIV_16 + * @arg @ref LL_RCC_PLLP_DIV_17 + * @arg @ref LL_RCC_PLLP_DIV_18 + * @arg @ref LL_RCC_PLLP_DIV_19 + * @arg @ref LL_RCC_PLLP_DIV_20 + * @arg @ref LL_RCC_PLLP_DIV_21 + * @arg @ref LL_RCC_PLLP_DIV_22 + * @arg @ref LL_RCC_PLLP_DIV_23 + * @arg @ref LL_RCC_PLLP_DIV_24 + * @arg @ref LL_RCC_PLLP_DIV_25 + * @arg @ref LL_RCC_PLLP_DIV_26 + * @arg @ref LL_RCC_PLLP_DIV_27 + * @arg @ref LL_RCC_PLLP_DIV_28 + * @arg @ref LL_RCC_PLLP_DIV_29 + * @arg @ref LL_RCC_PLLP_DIV_30 + * @arg @ref LL_RCC_PLLP_DIV_31 + * @retval PLL clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLCLK_SAI_FREQ(__INPUTFREQ__, __PLLM__, __PLLN__, __PLLP__) ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLN__) / \ + ((__PLLP__) >> RCC_PLLCFGR_PLLPDIV_Pos)) + +#else +/** + * @brief Helper macro to calculate the PLLCLK frequency used on SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLCLK_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLL_GetN (), @ref LL_RCC_PLL_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLN__ Between 8 and 86 + * @param __PLLP__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLP_DIV_7 + * @arg @ref LL_RCC_PLLP_DIV_17 + * @retval PLL clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLCLK_SAI_FREQ(__INPUTFREQ__, __PLLM__, __PLLN__, __PLLP__) ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLN__) / \ + (((__PLLP__) == LL_RCC_PLLP_DIV_7) ? 7U : 17U)) + +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +#endif /* RCC_PLLSAI1_SUPPORT */ + +/** + * @brief Helper macro to calculate the PLLCLK frequency used on 48M domain + * @note ex: @ref __LL_RCC_CALC_PLLCLK_48M_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLL_GetN (), @ref LL_RCC_PLL_GetQ ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + * @param __PLLN__ Between 8 and 86 or 127 depending on devices + * @param __PLLQ__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLQ_DIV_2 + * @arg @ref LL_RCC_PLLQ_DIV_4 + * @arg @ref LL_RCC_PLLQ_DIV_6 + * @arg @ref LL_RCC_PLLQ_DIV_8 + * @retval PLL clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLCLK_48M_FREQ(__INPUTFREQ__, __PLLM__, __PLLN__, __PLLQ__) ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLN__) / \ + ((((__PLLQ__) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U)) + +#if defined(RCC_PLLSAI1_SUPPORT) +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used for SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLLSAI1_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLSAI1M__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + * @param __PLLSAI1N__ Between 8 and 86 or 127 depending on devices + * @param __PLLSAI1P__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_2 + * @arg @ref LL_RCC_PLLSAI1P_DIV_3 + * @arg @ref LL_RCC_PLLSAI1P_DIV_4 + * @arg @ref LL_RCC_PLLSAI1P_DIV_5 + * @arg @ref LL_RCC_PLLSAI1P_DIV_6 + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_8 + * @arg @ref LL_RCC_PLLSAI1P_DIV_9 + * @arg @ref LL_RCC_PLLSAI1P_DIV_10 + * @arg @ref LL_RCC_PLLSAI1P_DIV_11 + * @arg @ref LL_RCC_PLLSAI1P_DIV_12 + * @arg @ref LL_RCC_PLLSAI1P_DIV_13 + * @arg @ref LL_RCC_PLLSAI1P_DIV_14 + * @arg @ref LL_RCC_PLLSAI1P_DIV_15 + * @arg @ref LL_RCC_PLLSAI1P_DIV_16 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @arg @ref LL_RCC_PLLSAI1P_DIV_18 + * @arg @ref LL_RCC_PLLSAI1P_DIV_19 + * @arg @ref LL_RCC_PLLSAI1P_DIV_20 + * @arg @ref LL_RCC_PLLSAI1P_DIV_21 + * @arg @ref LL_RCC_PLLSAI1P_DIV_22 + * @arg @ref LL_RCC_PLLSAI1P_DIV_23 + * @arg @ref LL_RCC_PLLSAI1P_DIV_24 + * @arg @ref LL_RCC_PLLSAI1P_DIV_25 + * @arg @ref LL_RCC_PLLSAI1P_DIV_26 + * @arg @ref LL_RCC_PLLSAI1P_DIV_27 + * @arg @ref LL_RCC_PLLSAI1P_DIV_28 + * @arg @ref LL_RCC_PLLSAI1P_DIV_29 + * @arg @ref LL_RCC_PLLSAI1P_DIV_30 + * @arg @ref LL_RCC_PLLSAI1P_DIV_31 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_SAI_FREQ(__INPUTFREQ__, __PLLSAI1M__, __PLLSAI1N__, __PLLSAI1P__) \ + ((__INPUTFREQ__) / ((((__PLLSAI1M__) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)) * (__PLLSAI1N__) / \ + ((__PLLSAI1P__) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)) + +#elif defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used for SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI1N__ Between 8 and 86 or 127 depending on devices + * @param __PLLSAI1P__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_2 + * @arg @ref LL_RCC_PLLSAI1P_DIV_3 + * @arg @ref LL_RCC_PLLSAI1P_DIV_4 + * @arg @ref LL_RCC_PLLSAI1P_DIV_5 + * @arg @ref LL_RCC_PLLSAI1P_DIV_6 + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_8 + * @arg @ref LL_RCC_PLLSAI1P_DIV_9 + * @arg @ref LL_RCC_PLLSAI1P_DIV_10 + * @arg @ref LL_RCC_PLLSAI1P_DIV_11 + * @arg @ref LL_RCC_PLLSAI1P_DIV_12 + * @arg @ref LL_RCC_PLLSAI1P_DIV_13 + * @arg @ref LL_RCC_PLLSAI1P_DIV_14 + * @arg @ref LL_RCC_PLLSAI1P_DIV_15 + * @arg @ref LL_RCC_PLLSAI1P_DIV_16 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @arg @ref LL_RCC_PLLSAI1P_DIV_18 + * @arg @ref LL_RCC_PLLSAI1P_DIV_19 + * @arg @ref LL_RCC_PLLSAI1P_DIV_20 + * @arg @ref LL_RCC_PLLSAI1P_DIV_21 + * @arg @ref LL_RCC_PLLSAI1P_DIV_22 + * @arg @ref LL_RCC_PLLSAI1P_DIV_23 + * @arg @ref LL_RCC_PLLSAI1P_DIV_24 + * @arg @ref LL_RCC_PLLSAI1P_DIV_25 + * @arg @ref LL_RCC_PLLSAI1P_DIV_26 + * @arg @ref LL_RCC_PLLSAI1P_DIV_27 + * @arg @ref LL_RCC_PLLSAI1P_DIV_28 + * @arg @ref LL_RCC_PLLSAI1P_DIV_29 + * @arg @ref LL_RCC_PLLSAI1P_DIV_30 + * @arg @ref LL_RCC_PLLSAI1P_DIV_31 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_SAI_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI1N__, __PLLSAI1P__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLSAI1N__) / \ + ((__PLLSAI1P__) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos)) + +#else +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used for SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI1N__ Between 8 and 86 + * @param __PLLSAI1P__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_SAI_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI1N__, __PLLSAI1P__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLSAI1N__) / \ + (((__PLLSAI1P__) == LL_RCC_PLLSAI1P_DIV_7) ? 7U : 17U)) + +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used on 48M domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_48M_FREQ (HSE_VALUE,@ref LL_RCC_PLLSAI1_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetQ ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLSAI1M__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + * @param __PLLSAI1N__ Between 8 and 86 or 127 depending on devices + * @param __PLLSAI1Q__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_8 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_48M_FREQ(__INPUTFREQ__, __PLLSAI1M__, __PLLSAI1N__, __PLLSAI1Q__) \ + ((__INPUTFREQ__) / ((((__PLLSAI1M__) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)) * (__PLLSAI1N__) / \ + ((((__PLLSAI1Q__) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U)) + +#else +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used on 48M domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_48M_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetQ ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI1N__ Between 8 and 86 + * @param __PLLSAI1Q__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_8 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_48M_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI1N__, __PLLSAI1Q__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLSAI1N__) / \ + ((((__PLLSAI1Q__) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U)) + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used on ADC domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_ADC_FREQ (HSE_VALUE,@ref LL_RCC_PLLSAI1_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetR ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLSAI1M__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + * @param __PLLSAI1N__ Between 8 and 86 or 127 depending on devices + * @param __PLLSAI1R__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1R_DIV_2 + * @arg @ref LL_RCC_PLLSAI1R_DIV_4 + * @arg @ref LL_RCC_PLLSAI1R_DIV_6 + * @arg @ref LL_RCC_PLLSAI1R_DIV_8 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_ADC_FREQ(__INPUTFREQ__, __PLLSAI1M__, __PLLSAI1N__, __PLLSAI1R__) \ + ((__INPUTFREQ__) / ((((__PLLSAI1M__) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U)) * (__PLLSAI1N__) / \ + ((((__PLLSAI1R__) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U)) + +#else +/** + * @brief Helper macro to calculate the PLLSAI1 frequency used on ADC domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI1_ADC_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI1_GetN (), @ref LL_RCC_PLLSAI1_GetR ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI1N__ Between 8 and 86 + * @param __PLLSAI1R__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1R_DIV_2 + * @arg @ref LL_RCC_PLLSAI1R_DIV_4 + * @arg @ref LL_RCC_PLLSAI1R_DIV_6 + * @arg @ref LL_RCC_PLLSAI1R_DIV_8 + * @retval PLLSAI1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI1_ADC_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI1N__, __PLLSAI1R__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLSAI1N__) / \ + ((((__PLLSAI1R__) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U)) + +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI2 frequency used for SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI2_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLLSAI2_GetDivider (), + * @ref LL_RCC_PLLSAI2_GetN (), @ref LL_RCC_PLLSAI2_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLSAI2M__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + * @param __PLLSAI2N__ Between 8 and 86 or 127 depending on devices + * @param __PLLSAI2P__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_2 + * @arg @ref LL_RCC_PLLSAI2P_DIV_3 + * @arg @ref LL_RCC_PLLSAI2P_DIV_4 + * @arg @ref LL_RCC_PLLSAI2P_DIV_5 + * @arg @ref LL_RCC_PLLSAI2P_DIV_6 + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_8 + * @arg @ref LL_RCC_PLLSAI2P_DIV_9 + * @arg @ref LL_RCC_PLLSAI2P_DIV_10 + * @arg @ref LL_RCC_PLLSAI2P_DIV_11 + * @arg @ref LL_RCC_PLLSAI2P_DIV_12 + * @arg @ref LL_RCC_PLLSAI2P_DIV_13 + * @arg @ref LL_RCC_PLLSAI2P_DIV_14 + * @arg @ref LL_RCC_PLLSAI2P_DIV_15 + * @arg @ref LL_RCC_PLLSAI2P_DIV_16 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @arg @ref LL_RCC_PLLSAI2P_DIV_18 + * @arg @ref LL_RCC_PLLSAI2P_DIV_19 + * @arg @ref LL_RCC_PLLSAI2P_DIV_20 + * @arg @ref LL_RCC_PLLSAI2P_DIV_21 + * @arg @ref LL_RCC_PLLSAI2P_DIV_22 + * @arg @ref LL_RCC_PLLSAI2P_DIV_23 + * @arg @ref LL_RCC_PLLSAI2P_DIV_24 + * @arg @ref LL_RCC_PLLSAI2P_DIV_25 + * @arg @ref LL_RCC_PLLSAI2P_DIV_26 + * @arg @ref LL_RCC_PLLSAI2P_DIV_27 + * @arg @ref LL_RCC_PLLSAI2P_DIV_28 + * @arg @ref LL_RCC_PLLSAI2P_DIV_29 + * @arg @ref LL_RCC_PLLSAI2P_DIV_30 + * @arg @ref LL_RCC_PLLSAI2P_DIV_31 + * @retval PLLSAI2 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI2_SAI_FREQ(__INPUTFREQ__, __PLLSAI2M__, __PLLSAI2N__, __PLLSAI2P__) \ + ((__INPUTFREQ__) / ((((__PLLSAI2M__) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)) * (__PLLSAI2N__) / \ + ((__PLLSAI2P__) >> RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)) + +#elif defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI2 frequency used for SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI2_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI2_GetN (), @ref LL_RCC_PLLSAI2_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI2N__ Between 8 and 86 or 127 depending on devices + * @param __PLLSAI2P__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_2 + * @arg @ref LL_RCC_PLLSAI2P_DIV_3 + * @arg @ref LL_RCC_PLLSAI2P_DIV_4 + * @arg @ref LL_RCC_PLLSAI2P_DIV_5 + * @arg @ref LL_RCC_PLLSAI2P_DIV_6 + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_8 + * @arg @ref LL_RCC_PLLSAI2P_DIV_9 + * @arg @ref LL_RCC_PLLSAI2P_DIV_10 + * @arg @ref LL_RCC_PLLSAI2P_DIV_11 + * @arg @ref LL_RCC_PLLSAI2P_DIV_12 + * @arg @ref LL_RCC_PLLSAI2P_DIV_13 + * @arg @ref LL_RCC_PLLSAI2P_DIV_14 + * @arg @ref LL_RCC_PLLSAI2P_DIV_15 + * @arg @ref LL_RCC_PLLSAI2P_DIV_16 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @arg @ref LL_RCC_PLLSAI2P_DIV_18 + * @arg @ref LL_RCC_PLLSAI2P_DIV_19 + * @arg @ref LL_RCC_PLLSAI2P_DIV_20 + * @arg @ref LL_RCC_PLLSAI2P_DIV_21 + * @arg @ref LL_RCC_PLLSAI2P_DIV_22 + * @arg @ref LL_RCC_PLLSAI2P_DIV_23 + * @arg @ref LL_RCC_PLLSAI2P_DIV_24 + * @arg @ref LL_RCC_PLLSAI2P_DIV_25 + * @arg @ref LL_RCC_PLLSAI2P_DIV_26 + * @arg @ref LL_RCC_PLLSAI2P_DIV_27 + * @arg @ref LL_RCC_PLLSAI2P_DIV_28 + * @arg @ref LL_RCC_PLLSAI2P_DIV_29 + * @arg @ref LL_RCC_PLLSAI2P_DIV_30 + * @arg @ref LL_RCC_PLLSAI2P_DIV_31 + * @retval PLLSAI2 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI2_SAI_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI2N__, __PLLSAI2P__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLSAI2N__) / \ + ((__PLLSAI2P__) >> RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos)) + +#else +/** + * @brief Helper macro to calculate the PLLSAI2 frequency used for SAI domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI2_SAI_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI2_GetN (), @ref LL_RCC_PLLSAI2_GetP ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI2N__ Between 8 and 86 + * @param __PLLSAI2P__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @retval PLLSAI2 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI2_SAI_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI2N__, __PLLSAI2P__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1)) * (__PLLSAI2N__) / \ + (((__PLLSAI2P__) == LL_RCC_PLLSAI2P_DIV_7) ? 7U : 17U)) + +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#if defined(LTDC) +/** + * @brief Helper macro to calculate the PLLSAI2 frequency used for LTDC domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI2_LTDC_FREQ (HSE_VALUE,@ref LL_RCC_PLLSAI2_GetDivider (), + * @ref LL_RCC_PLLSAI2_GetN (), @ref LL_RCC_PLLSAI2_GetR (), @ref LL_RCC_PLLSAI2_GetDIVR ()); + * @param __INPUTFREQ__ PLL Input frequency (based on HSE/HSI/MSI) + * @param __PLLSAI2M__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + * @param __PLLSAI2N__ Between 8 and 127 + * @param __PLLSAI2R__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2R_DIV_2 + * @arg @ref LL_RCC_PLLSAI2R_DIV_4 + * @arg @ref LL_RCC_PLLSAI2R_DIV_6 + * @arg @ref LL_RCC_PLLSAI2R_DIV_8 + * @param __PLLSAI2DIVR__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_2 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_4 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_8 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_16 + * @retval PLLSAI2 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI2_LTDC_FREQ(__INPUTFREQ__, __PLLSAI2M__, __PLLSAI2N__, __PLLSAI2R__, __PLLSAI2DIVR__) \ + (((__INPUTFREQ__) / (((__PLLSAI2M__)>> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)) * (__PLLSAI2N__) / \ + (((((__PLLSAI2R__) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos ) + 1U) << 1U) * (2UL << ((__PLLSAI2DIVR__) >> RCC_CCIPR2_PLLSAI2DIVR_Pos)))) +#elif defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Helper macro to calculate the PLLSAI2 frequency used on ADC domain + * @note ex: @ref __LL_RCC_CALC_PLLSAI2_ADC_FREQ (HSE_VALUE,@ref LL_RCC_PLL_GetDivider (), + * @ref LL_RCC_PLLSAI2_GetN (), @ref LL_RCC_PLLSAI2_GetR ()); + * @param __INPUTFREQ__ PLL Input frequency (based on MSI/HSE/HSI) + * @param __PLLM__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param __PLLSAI2N__ Between 8 and 86 + * @param __PLLSAI2R__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2R_DIV_2 + * @arg @ref LL_RCC_PLLSAI2R_DIV_4 + * @arg @ref LL_RCC_PLLSAI2R_DIV_6 + * @arg @ref LL_RCC_PLLSAI2R_DIV_8 + * @retval PLLSAI2 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI2_ADC_FREQ(__INPUTFREQ__, __PLLM__, __PLLSAI2N__, __PLLSAI2R__) \ + ((__INPUTFREQ__) / ((((__PLLM__)>> RCC_PLLCFGR_PLLM_Pos) + 1U)) * (__PLLSAI2N__) / \ + ((((__PLLSAI2R__) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos ) + 1U) << 1U)) + +#endif /* LTDC */ + +#if defined(DSI) +/** + * @brief Helper macro to calculate the PLLDSICLK frequency used on DSI + * @note ex: @ref __LL_RCC_CALC_PLLSAI2_DSI_FREQ (HSE_VALUE,@ref LL_RCC_PLLSAI2_GetDivider (), + * @ref LL_RCC_PLLSAI2_GetN (), @ref LL_RCC_PLLSAI2_GetQ ()); + * @param __INPUTFREQ__ PLL Input frequency (based on HSE/HSI/MSI) + * @param __PLLSAI2M__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + * @param __PLLSAI2N__ Between 8 and 127 + * @param __PLLSAI2Q__ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_8 + * @retval PLL clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PLLSAI2_DSI_FREQ(__INPUTFREQ__, __PLLSAI2M__, __PLLSAI2N__, __PLLSAI2Q__) \ + ((__INPUTFREQ__) / ((((__PLLSAI2M__) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U)) * (__PLLSAI2N__) / \ + ((((__PLLSAI2Q__) >> RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + 1U) << 1U)) +#endif /* DSI */ + + + +/** + * @brief Helper macro to calculate the HCLK frequency + * @param __SYSCLKFREQ__ SYSCLK frequency (based on MSI/HSE/HSI/PLLCLK) + * @param __AHBPRESCALER__ This parameter can be one of the following values: + * @arg @ref LL_RCC_SYSCLK_DIV_1 + * @arg @ref LL_RCC_SYSCLK_DIV_2 + * @arg @ref LL_RCC_SYSCLK_DIV_4 + * @arg @ref LL_RCC_SYSCLK_DIV_8 + * @arg @ref LL_RCC_SYSCLK_DIV_16 + * @arg @ref LL_RCC_SYSCLK_DIV_64 + * @arg @ref LL_RCC_SYSCLK_DIV_128 + * @arg @ref LL_RCC_SYSCLK_DIV_256 + * @arg @ref LL_RCC_SYSCLK_DIV_512 + * @retval HCLK clock frequency (in Hz) + */ +#define __LL_RCC_CALC_HCLK_FREQ(__SYSCLKFREQ__, __AHBPRESCALER__) ((__SYSCLKFREQ__) >> AHBPrescTable[((__AHBPRESCALER__) & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos]) + +/** + * @brief Helper macro to calculate the PCLK1 frequency (ABP1) + * @param __HCLKFREQ__ HCLK frequency + * @param __APB1PRESCALER__ This parameter can be one of the following values: + * @arg @ref LL_RCC_APB1_DIV_1 + * @arg @ref LL_RCC_APB1_DIV_2 + * @arg @ref LL_RCC_APB1_DIV_4 + * @arg @ref LL_RCC_APB1_DIV_8 + * @arg @ref LL_RCC_APB1_DIV_16 + * @retval PCLK1 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PCLK1_FREQ(__HCLKFREQ__, __APB1PRESCALER__) ((__HCLKFREQ__) >> APBPrescTable[(__APB1PRESCALER__) >> RCC_CFGR_PPRE1_Pos]) + +/** + * @brief Helper macro to calculate the PCLK2 frequency (ABP2) + * @param __HCLKFREQ__ HCLK frequency + * @param __APB2PRESCALER__ This parameter can be one of the following values: + * @arg @ref LL_RCC_APB2_DIV_1 + * @arg @ref LL_RCC_APB2_DIV_2 + * @arg @ref LL_RCC_APB2_DIV_4 + * @arg @ref LL_RCC_APB2_DIV_8 + * @arg @ref LL_RCC_APB2_DIV_16 + * @retval PCLK2 clock frequency (in Hz) + */ +#define __LL_RCC_CALC_PCLK2_FREQ(__HCLKFREQ__, __APB2PRESCALER__) ((__HCLKFREQ__) >> APBPrescTable[(__APB2PRESCALER__) >> RCC_CFGR_PPRE2_Pos]) + +/** + * @brief Helper macro to calculate the MSI frequency (in Hz) + * @note __MSISEL__ can be retrieved thanks to function LL_RCC_MSI_IsEnabledRangeSelect() + * @note if __MSISEL__ is equal to LL_RCC_MSIRANGESEL_STANDBY, + * __MSIRANGE__can be retrieved by LL_RCC_MSI_GetRangeAfterStandby() + * else by LL_RCC_MSI_GetRange() + * ex: __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + * (LL_RCC_MSI_IsEnabledRangeSelect()? + * LL_RCC_MSI_GetRange(): + * LL_RCC_MSI_GetRangeAfterStandby())) + * @param __MSISEL__ This parameter can be one of the following values: + * @arg @ref LL_RCC_MSIRANGESEL_STANDBY + * @arg @ref LL_RCC_MSIRANGESEL_RUN + * @param __MSIRANGE__ This parameter can be one of the following values: + * @arg @ref LL_RCC_MSIRANGE_0 + * @arg @ref LL_RCC_MSIRANGE_1 + * @arg @ref LL_RCC_MSIRANGE_2 + * @arg @ref LL_RCC_MSIRANGE_3 + * @arg @ref LL_RCC_MSIRANGE_4 + * @arg @ref LL_RCC_MSIRANGE_5 + * @arg @ref LL_RCC_MSIRANGE_6 + * @arg @ref LL_RCC_MSIRANGE_7 + * @arg @ref LL_RCC_MSIRANGE_8 + * @arg @ref LL_RCC_MSIRANGE_9 + * @arg @ref LL_RCC_MSIRANGE_10 + * @arg @ref LL_RCC_MSIRANGE_11 + * @arg @ref LL_RCC_MSISRANGE_4 + * @arg @ref LL_RCC_MSISRANGE_5 + * @arg @ref LL_RCC_MSISRANGE_6 + * @arg @ref LL_RCC_MSISRANGE_7 + * @retval MSI clock frequency (in Hz) + */ +#define __LL_RCC_CALC_MSI_FREQ(__MSISEL__, __MSIRANGE__) (((__MSISEL__) == LL_RCC_MSIRANGESEL_STANDBY) ? \ + (MSIRangeTable[(__MSIRANGE__) >> 8U]) : \ + (MSIRangeTable[(__MSIRANGE__) >> 4U])) + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup RCC_LL_Exported_Functions RCC Exported Functions + * @{ + */ + +/** @defgroup RCC_LL_EF_HSE HSE + * @{ + */ + +/** + * @brief Enable the Clock Security System. + * @rmtoll CR CSSON LL_RCC_HSE_EnableCSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSE_EnableCSS(void) +{ + SET_BIT(RCC->CR, RCC_CR_CSSON); +} + +/** + * @brief Enable HSE external oscillator (HSE Bypass) + * @rmtoll CR HSEBYP LL_RCC_HSE_EnableBypass + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSE_EnableBypass(void) +{ + SET_BIT(RCC->CR, RCC_CR_HSEBYP); +} + +/** + * @brief Disable HSE external oscillator (HSE Bypass) + * @rmtoll CR HSEBYP LL_RCC_HSE_DisableBypass + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSE_DisableBypass(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP); +} + +/** + * @brief Enable HSE crystal oscillator (HSE ON) + * @rmtoll CR HSEON LL_RCC_HSE_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSE_Enable(void) +{ + SET_BIT(RCC->CR, RCC_CR_HSEON); +} + +/** + * @brief Disable HSE crystal oscillator (HSE ON) + * @rmtoll CR HSEON LL_RCC_HSE_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSE_Disable(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_HSEON); +} + +/** + * @brief Check if HSE oscillator Ready + * @rmtoll CR HSERDY LL_RCC_HSE_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_HSE_IsReady(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_HSERDY) == RCC_CR_HSERDY) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_HSI HSI + * @{ + */ + +/** + * @brief Enable HSI even in stop mode + * @note HSI oscillator is forced ON even in Stop mode + * @rmtoll CR HSIKERON LL_RCC_HSI_EnableInStopMode + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_EnableInStopMode(void) +{ + SET_BIT(RCC->CR, RCC_CR_HSIKERON); +} + +/** + * @brief Disable HSI in stop mode + * @rmtoll CR HSIKERON LL_RCC_HSI_DisableInStopMode + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_DisableInStopMode(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_HSIKERON); +} + +/** + * @brief Check if HSI is enabled in stop mode + * @rmtoll CR HSIKERON LL_RCC_HSI_IsEnabledInStopMode + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_HSI_IsEnabledInStopMode(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_HSIKERON) == RCC_CR_HSIKERON) ? 1UL : 0UL); +} + +/** + * @brief Enable HSI oscillator + * @rmtoll CR HSION LL_RCC_HSI_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_Enable(void) +{ + SET_BIT(RCC->CR, RCC_CR_HSION); +} + +/** + * @brief Disable HSI oscillator + * @rmtoll CR HSION LL_RCC_HSI_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_Disable(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_HSION); +} + +/** + * @brief Check if HSI clock is ready + * @rmtoll CR HSIRDY LL_RCC_HSI_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_HSI_IsReady(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RCC_CR_HSIRDY) ? 1UL : 0UL); +} + +/** + * @brief Enable HSI Automatic from stop mode + * @rmtoll CR HSIASFS LL_RCC_HSI_EnableAutoFromStop + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_EnableAutoFromStop(void) +{ + SET_BIT(RCC->CR, RCC_CR_HSIASFS); +} + +/** + * @brief Disable HSI Automatic from stop mode + * @rmtoll CR HSIASFS LL_RCC_HSI_DisableAutoFromStop + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_DisableAutoFromStop(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_HSIASFS); +} +/** + * @brief Get HSI Calibration value + * @note When HSITRIM is written, HSICAL is updated with the sum of + * HSITRIM and the factory trim value + * @rmtoll ICSCR HSICAL LL_RCC_HSI_GetCalibration + * @retval Between Min_Data = 0x00 and Max_Data = 0xFF + */ +__STATIC_INLINE uint32_t LL_RCC_HSI_GetCalibration(void) +{ + return (uint32_t)(READ_BIT(RCC->ICSCR, RCC_ICSCR_HSICAL) >> RCC_ICSCR_HSICAL_Pos); +} + +/** + * @brief Set HSI Calibration trimming + * @note user-programmable trimming value that is added to the HSICAL + * @note Default value is 16 on STM32L43x/STM32L44x/STM32L47x/STM32L48x or 64 on other devices, + * which, when added to the HSICAL value, should trim the HSI to 16 MHz +/- 1 % + * @rmtoll ICSCR HSITRIM LL_RCC_HSI_SetCalibTrimming + * @param Value Between Min_Data = 0 and Max_Data = 31 on STM32L43x/STM32L44x/STM32L47x/STM32L48x or + * between Min_Data = 0 and Max_Data = 127 on other devices + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI_SetCalibTrimming(uint32_t Value) +{ + MODIFY_REG(RCC->ICSCR, RCC_ICSCR_HSITRIM, Value << RCC_ICSCR_HSITRIM_Pos); +} + +/** + * @brief Get HSI Calibration trimming + * @rmtoll ICSCR HSITRIM LL_RCC_HSI_GetCalibTrimming + * @retval Between Min_Data = 0 and Max_Data = 31 on STM32L43x/STM32L44x/STM32L47x/STM32L48x or + * between Min_Data = 0 and Max_Data = 127 on other devices + */ +__STATIC_INLINE uint32_t LL_RCC_HSI_GetCalibTrimming(void) +{ + return (uint32_t)(READ_BIT(RCC->ICSCR, RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos); +} + +/** + * @} + */ + +#if defined(RCC_HSI48_SUPPORT) +/** @defgroup RCC_LL_EF_HSI48 HSI48 + * @{ + */ + +/** + * @brief Enable HSI48 + * @rmtoll CRRCR HSI48ON LL_RCC_HSI48_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI48_Enable(void) +{ + SET_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON); +} + +/** + * @brief Disable HSI48 + * @rmtoll CRRCR HSI48ON LL_RCC_HSI48_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_HSI48_Disable(void) +{ + CLEAR_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON); +} + +/** + * @brief Check if HSI48 oscillator Ready + * @rmtoll CRRCR HSI48RDY LL_RCC_HSI48_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_HSI48_IsReady(void) +{ + return ((READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == RCC_CRRCR_HSI48RDY) ? 1UL : 0UL); +} + +/** + * @brief Get HSI48 Calibration value + * @rmtoll CRRCR HSI48CAL LL_RCC_HSI48_GetCalibration + * @retval Between Min_Data = 0x00 and Max_Data = 0x1FF + */ +__STATIC_INLINE uint32_t LL_RCC_HSI48_GetCalibration(void) +{ + return (uint32_t)(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48CAL) >> RCC_CRRCR_HSI48CAL_Pos); +} + +/** + * @} + */ +#endif /* RCC_HSI48_SUPPORT */ + +/** @defgroup RCC_LL_EF_LSE LSE + * @{ + */ + +/** + * @brief Enable Low Speed External (LSE) crystal. + * @rmtoll BDCR LSEON LL_RCC_LSE_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_Enable(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEON); +} + +/** + * @brief Disable Low Speed External (LSE) crystal. + * @rmtoll BDCR LSEON LL_RCC_LSE_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_Disable(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON); +} + +/** + * @brief Enable external clock source (LSE bypass). + * @rmtoll BDCR LSEBYP LL_RCC_LSE_EnableBypass + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_EnableBypass(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); +} + +/** + * @brief Disable external clock source (LSE bypass). + * @rmtoll BDCR LSEBYP LL_RCC_LSE_DisableBypass + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_DisableBypass(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP); +} + +/** + * @brief Set LSE oscillator drive capability + * @note The oscillator is in Xtal mode when it is not in bypass mode. + * @rmtoll BDCR LSEDRV LL_RCC_LSE_SetDriveCapability + * @param LSEDrive This parameter can be one of the following values: + * @arg @ref LL_RCC_LSEDRIVE_LOW + * @arg @ref LL_RCC_LSEDRIVE_MEDIUMLOW + * @arg @ref LL_RCC_LSEDRIVE_MEDIUMHIGH + * @arg @ref LL_RCC_LSEDRIVE_HIGH + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_SetDriveCapability(uint32_t LSEDrive) +{ + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSEDRV, LSEDrive); +} + +/** + * @brief Get LSE oscillator drive capability + * @rmtoll BDCR LSEDRV LL_RCC_LSE_GetDriveCapability + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_LSEDRIVE_LOW + * @arg @ref LL_RCC_LSEDRIVE_MEDIUMLOW + * @arg @ref LL_RCC_LSEDRIVE_MEDIUMHIGH + * @arg @ref LL_RCC_LSEDRIVE_HIGH + */ +__STATIC_INLINE uint32_t LL_RCC_LSE_GetDriveCapability(void) +{ + return (uint32_t)(READ_BIT(RCC->BDCR, RCC_BDCR_LSEDRV)); +} + +/** + * @brief Enable Clock security system on LSE. + * @rmtoll BDCR LSECSSON LL_RCC_LSE_EnableCSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_EnableCSS(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON); +} + +/** + * @brief Disable Clock security system on LSE. + * @note Clock security system can be disabled only after a LSE + * failure detection. In that case it MUST be disabled by software. + * @rmtoll BDCR LSECSSON LL_RCC_LSE_DisableCSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_DisableCSS(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON); +} + +/** + * @brief Check if LSE oscillator Ready + * @rmtoll BDCR LSERDY LL_RCC_LSE_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_LSE_IsReady(void) +{ + return ((READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RCC_BDCR_LSERDY) ? 1UL : 0UL); +} + +/** + * @brief Check if CSS on LSE failure Detection + * @rmtoll BDCR LSECSSD LL_RCC_LSE_IsCSSDetected + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_LSE_IsCSSDetected(void) +{ + return ((READ_BIT(RCC->BDCR, RCC_BDCR_LSECSSD) == RCC_BDCR_LSECSSD) ? 1UL : 0UL); +} + +#if defined(RCC_BDCR_LSESYSDIS) +/** + * @brief Disable LSE oscillator propagation + * @note LSE clock is not propagated to any peripheral except to RTC which remains clocked + * @note A 2 LSE-clock delay is needed for LSESYSDIS setting to be taken into account + * @rmtoll BDCR LSESYSDIS LL_RCC_LSE_DisablePropagation + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_DisablePropagation(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSESYSDIS); +} + +/** + * @brief Enable LSE oscillator propagation + * @note A 2 LSE-clock delay is needed for LSESYSDIS resetting to be taken into account + * @rmtoll BDCR LSESYSDIS LL_RCC_LSE_EnablePropagation + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSE_EnablePropagation(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSESYSDIS); +} + +/** + * @brief Check if LSE oscillator propagation is enabled + * @rmtoll BDCR LSESYSDIS LL_RCC_LSE_IsPropagationEnabled + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_LSE_IsPropagationEnabled(void) +{ + return ((READ_BIT(RCC->BDCR, RCC_BDCR_LSESYSDIS) == 0U) ? 1UL : 0UL); +} +#endif /* RCC_BDCR_LSESYSDIS */ +/** + * @} + */ + +/** @defgroup RCC_LL_EF_LSI LSI + * @{ + */ + +/** + * @brief Enable LSI Oscillator + * @rmtoll CSR LSION LL_RCC_LSI_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSI_Enable(void) +{ + SET_BIT(RCC->CSR, RCC_CSR_LSION); +} + +/** + * @brief Disable LSI Oscillator + * @rmtoll CSR LSION LL_RCC_LSI_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSI_Disable(void) +{ + CLEAR_BIT(RCC->CSR, RCC_CSR_LSION); +} + +/** + * @brief Check if LSI is Ready + * @rmtoll CSR LSIRDY LL_RCC_LSI_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_LSI_IsReady(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RCC_CSR_LSIRDY) ? 1UL : 0UL); +} + +#if defined(RCC_CSR_LSIPREDIV) +/** + * @brief Set LSI division factor + * @rmtoll CSR LSIPREDIV LL_RCC_LSI_SetPrediv + * @param LSI_PREDIV This parameter can be one of the following values: + * @arg @ref LL_RCC_LSI_PREDIV_1 + * @arg @ref LL_RCC_LSI_PREDIV_128 + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSI_SetPrediv(uint32_t LSI_PREDIV) +{ + MODIFY_REG(RCC->CSR, RCC_CSR_LSIPREDIV, LSI_PREDIV); +} + +/** + * @brief Get LSI division factor + * @rmtoll CSR LSIPREDIV LL_RCC_LSI_GetPrediv + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_LSI_PREDIV_1 + * @arg @ref LL_RCC_LSI_PREDIV_128 + */ +__STATIC_INLINE uint32_t LL_RCC_LSI_GetPrediv(void) +{ + return (READ_BIT(RCC->CSR, RCC_CSR_LSIPREDIV)); +} +#endif /* RCC_CSR_LSIPREDIV */ + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_MSI MSI + * @{ + */ + +/** + * @brief Enable MSI oscillator + * @rmtoll CR MSION LL_RCC_MSI_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_Enable(void) +{ + SET_BIT(RCC->CR, RCC_CR_MSION); +} + +/** + * @brief Disable MSI oscillator + * @rmtoll CR MSION LL_RCC_MSI_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_Disable(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_MSION); +} + +/** + * @brief Check if MSI oscillator Ready + * @rmtoll CR MSIRDY LL_RCC_MSI_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_MSI_IsReady(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RCC_CR_MSIRDY) ? 1UL : 0UL); +} + +/** + * @brief Enable MSI PLL-mode (Hardware auto calibration with LSE) + * @note MSIPLLEN must be enabled after LSE is enabled (LSEON enabled) + * and ready (LSERDY set by hardware) + * @note hardware protection to avoid enabling MSIPLLEN if LSE is not + * ready + * @rmtoll CR MSIPLLEN LL_RCC_MSI_EnablePLLMode + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_EnablePLLMode(void) +{ + SET_BIT(RCC->CR, RCC_CR_MSIPLLEN); +} + +/** + * @brief Disable MSI-PLL mode + * @note cleared by hardware when LSE is disabled (LSEON = 0) or when + * the Clock Security System on LSE detects a LSE failure + * @rmtoll CR MSIPLLEN LL_RCC_MSI_DisablePLLMode + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_DisablePLLMode(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN); +} + +/** + * @brief Enable MSI clock range selection with MSIRANGE register + * @note Write 0 has no effect. After a standby or a reset + * MSIRGSEL is at 0 and the MSI range value is provided by + * MSISRANGE + * @rmtoll CR MSIRGSEL LL_RCC_MSI_EnableRangeSelection + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_EnableRangeSelection(void) +{ + SET_BIT(RCC->CR, RCC_CR_MSIRGSEL); +} + +/** + * @brief Check if MSI clock range is selected with MSIRANGE register + * @rmtoll CR MSIRGSEL LL_RCC_MSI_IsEnabledRangeSelect + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_MSI_IsEnabledRangeSelect(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RCC_CR_MSIRGSEL) ? 1UL : 0UL); +} + +/** + * @brief Configure the Internal Multi Speed oscillator (MSI) clock range in run mode. + * @rmtoll CR MSIRANGE LL_RCC_MSI_SetRange + * @param Range This parameter can be one of the following values: + * @arg @ref LL_RCC_MSIRANGE_0 + * @arg @ref LL_RCC_MSIRANGE_1 + * @arg @ref LL_RCC_MSIRANGE_2 + * @arg @ref LL_RCC_MSIRANGE_3 + * @arg @ref LL_RCC_MSIRANGE_4 + * @arg @ref LL_RCC_MSIRANGE_5 + * @arg @ref LL_RCC_MSIRANGE_6 + * @arg @ref LL_RCC_MSIRANGE_7 + * @arg @ref LL_RCC_MSIRANGE_8 + * @arg @ref LL_RCC_MSIRANGE_9 + * @arg @ref LL_RCC_MSIRANGE_10 + * @arg @ref LL_RCC_MSIRANGE_11 + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_SetRange(uint32_t Range) +{ + MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, Range); +} + +/** + * @brief Get the Internal Multi Speed oscillator (MSI) clock range in run mode. + * @rmtoll CR MSIRANGE LL_RCC_MSI_GetRange + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_MSIRANGE_0 + * @arg @ref LL_RCC_MSIRANGE_1 + * @arg @ref LL_RCC_MSIRANGE_2 + * @arg @ref LL_RCC_MSIRANGE_3 + * @arg @ref LL_RCC_MSIRANGE_4 + * @arg @ref LL_RCC_MSIRANGE_5 + * @arg @ref LL_RCC_MSIRANGE_6 + * @arg @ref LL_RCC_MSIRANGE_7 + * @arg @ref LL_RCC_MSIRANGE_8 + * @arg @ref LL_RCC_MSIRANGE_9 + * @arg @ref LL_RCC_MSIRANGE_10 + * @arg @ref LL_RCC_MSIRANGE_11 + */ +__STATIC_INLINE uint32_t LL_RCC_MSI_GetRange(void) +{ + return (uint32_t)(READ_BIT(RCC->CR, RCC_CR_MSIRANGE)); +} + +/** + * @brief Configure MSI range used after standby + * @rmtoll CSR MSISRANGE LL_RCC_MSI_SetRangeAfterStandby + * @param Range This parameter can be one of the following values: + * @arg @ref LL_RCC_MSISRANGE_4 + * @arg @ref LL_RCC_MSISRANGE_5 + * @arg @ref LL_RCC_MSISRANGE_6 + * @arg @ref LL_RCC_MSISRANGE_7 + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_SetRangeAfterStandby(uint32_t Range) +{ + MODIFY_REG(RCC->CSR, RCC_CSR_MSISRANGE, Range); +} + +/** + * @brief Get MSI range used after standby + * @rmtoll CSR MSISRANGE LL_RCC_MSI_GetRangeAfterStandby + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_MSISRANGE_4 + * @arg @ref LL_RCC_MSISRANGE_5 + * @arg @ref LL_RCC_MSISRANGE_6 + * @arg @ref LL_RCC_MSISRANGE_7 + */ +__STATIC_INLINE uint32_t LL_RCC_MSI_GetRangeAfterStandby(void) +{ + return (uint32_t)(READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE)); +} + +/** + * @brief Get MSI Calibration value + * @note When MSITRIM is written, MSICAL is updated with the sum of + * MSITRIM and the factory trim value + * @rmtoll ICSCR MSICAL LL_RCC_MSI_GetCalibration + * @retval Between Min_Data = 0 and Max_Data = 255 + */ +__STATIC_INLINE uint32_t LL_RCC_MSI_GetCalibration(void) +{ + return (uint32_t)(READ_BIT(RCC->ICSCR, RCC_ICSCR_MSICAL) >> RCC_ICSCR_MSICAL_Pos); +} + +/** + * @brief Set MSI Calibration trimming + * @note user-programmable trimming value that is added to the MSICAL + * @rmtoll ICSCR MSITRIM LL_RCC_MSI_SetCalibTrimming + * @param Value Between Min_Data = 0 and Max_Data = 255 + * @retval None + */ +__STATIC_INLINE void LL_RCC_MSI_SetCalibTrimming(uint32_t Value) +{ + MODIFY_REG(RCC->ICSCR, RCC_ICSCR_MSITRIM, Value << RCC_ICSCR_MSITRIM_Pos); +} + +/** + * @brief Get MSI Calibration trimming + * @rmtoll ICSCR MSITRIM LL_RCC_MSI_GetCalibTrimming + * @retval Between 0 and 255 + */ +__STATIC_INLINE uint32_t LL_RCC_MSI_GetCalibTrimming(void) +{ + return (uint32_t)(READ_BIT(RCC->ICSCR, RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos); +} + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_LSCO LSCO + * @{ + */ + +/** + * @brief Enable Low speed clock + * @rmtoll BDCR LSCOEN LL_RCC_LSCO_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSCO_Enable(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_LSCOEN); +} + +/** + * @brief Disable Low speed clock + * @rmtoll BDCR LSCOEN LL_RCC_LSCO_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSCO_Disable(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSCOEN); +} + +/** + * @brief Configure Low speed clock selection + * @rmtoll BDCR LSCOSEL LL_RCC_LSCO_SetSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_LSCO_CLKSOURCE_LSI + * @arg @ref LL_RCC_LSCO_CLKSOURCE_LSE + * @retval None + */ +__STATIC_INLINE void LL_RCC_LSCO_SetSource(uint32_t Source) +{ + MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL, Source); +} + +/** + * @brief Get Low speed clock selection + * @rmtoll BDCR LSCOSEL LL_RCC_LSCO_GetSource + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_LSCO_CLKSOURCE_LSI + * @arg @ref LL_RCC_LSCO_CLKSOURCE_LSE + */ +__STATIC_INLINE uint32_t LL_RCC_LSCO_GetSource(void) +{ + return (uint32_t)(READ_BIT(RCC->BDCR, RCC_BDCR_LSCOSEL)); +} + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_System System + * @{ + */ + +/** + * @brief Configure the system clock source + * @rmtoll CFGR SW LL_RCC_SetSysClkSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_SYS_CLKSOURCE_MSI + * @arg @ref LL_RCC_SYS_CLKSOURCE_HSI + * @arg @ref LL_RCC_SYS_CLKSOURCE_HSE + * @arg @ref LL_RCC_SYS_CLKSOURCE_PLL + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetSysClkSource(uint32_t Source) +{ + MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, Source); +} + +/** + * @brief Get the system clock source + * @rmtoll CFGR SWS LL_RCC_GetSysClkSource + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_SYS_CLKSOURCE_STATUS_MSI + * @arg @ref LL_RCC_SYS_CLKSOURCE_STATUS_HSI + * @arg @ref LL_RCC_SYS_CLKSOURCE_STATUS_HSE + * @arg @ref LL_RCC_SYS_CLKSOURCE_STATUS_PLL + */ +__STATIC_INLINE uint32_t LL_RCC_GetSysClkSource(void) +{ + return (uint32_t)(READ_BIT(RCC->CFGR, RCC_CFGR_SWS)); +} + +/** + * @brief Set AHB prescaler + * @rmtoll CFGR HPRE LL_RCC_SetAHBPrescaler + * @param Prescaler This parameter can be one of the following values: + * @arg @ref LL_RCC_SYSCLK_DIV_1 + * @arg @ref LL_RCC_SYSCLK_DIV_2 + * @arg @ref LL_RCC_SYSCLK_DIV_4 + * @arg @ref LL_RCC_SYSCLK_DIV_8 + * @arg @ref LL_RCC_SYSCLK_DIV_16 + * @arg @ref LL_RCC_SYSCLK_DIV_64 + * @arg @ref LL_RCC_SYSCLK_DIV_128 + * @arg @ref LL_RCC_SYSCLK_DIV_256 + * @arg @ref LL_RCC_SYSCLK_DIV_512 + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetAHBPrescaler(uint32_t Prescaler) +{ + MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, Prescaler); +} + +/** + * @brief Set APB1 prescaler + * @rmtoll CFGR PPRE1 LL_RCC_SetAPB1Prescaler + * @param Prescaler This parameter can be one of the following values: + * @arg @ref LL_RCC_APB1_DIV_1 + * @arg @ref LL_RCC_APB1_DIV_2 + * @arg @ref LL_RCC_APB1_DIV_4 + * @arg @ref LL_RCC_APB1_DIV_8 + * @arg @ref LL_RCC_APB1_DIV_16 + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetAPB1Prescaler(uint32_t Prescaler) +{ + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, Prescaler); +} + +/** + * @brief Set APB2 prescaler + * @rmtoll CFGR PPRE2 LL_RCC_SetAPB2Prescaler + * @param Prescaler This parameter can be one of the following values: + * @arg @ref LL_RCC_APB2_DIV_1 + * @arg @ref LL_RCC_APB2_DIV_2 + * @arg @ref LL_RCC_APB2_DIV_4 + * @arg @ref LL_RCC_APB2_DIV_8 + * @arg @ref LL_RCC_APB2_DIV_16 + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetAPB2Prescaler(uint32_t Prescaler) +{ + MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, Prescaler); +} + +/** + * @brief Get AHB prescaler + * @rmtoll CFGR HPRE LL_RCC_GetAHBPrescaler + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_SYSCLK_DIV_1 + * @arg @ref LL_RCC_SYSCLK_DIV_2 + * @arg @ref LL_RCC_SYSCLK_DIV_4 + * @arg @ref LL_RCC_SYSCLK_DIV_8 + * @arg @ref LL_RCC_SYSCLK_DIV_16 + * @arg @ref LL_RCC_SYSCLK_DIV_64 + * @arg @ref LL_RCC_SYSCLK_DIV_128 + * @arg @ref LL_RCC_SYSCLK_DIV_256 + * @arg @ref LL_RCC_SYSCLK_DIV_512 + */ +__STATIC_INLINE uint32_t LL_RCC_GetAHBPrescaler(void) +{ + return (uint32_t)(READ_BIT(RCC->CFGR, RCC_CFGR_HPRE)); +} + +/** + * @brief Get APB1 prescaler + * @rmtoll CFGR PPRE1 LL_RCC_GetAPB1Prescaler + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_APB1_DIV_1 + * @arg @ref LL_RCC_APB1_DIV_2 + * @arg @ref LL_RCC_APB1_DIV_4 + * @arg @ref LL_RCC_APB1_DIV_8 + * @arg @ref LL_RCC_APB1_DIV_16 + */ +__STATIC_INLINE uint32_t LL_RCC_GetAPB1Prescaler(void) +{ + return (uint32_t)(READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1)); +} + +/** + * @brief Get APB2 prescaler + * @rmtoll CFGR PPRE2 LL_RCC_GetAPB2Prescaler + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_APB2_DIV_1 + * @arg @ref LL_RCC_APB2_DIV_2 + * @arg @ref LL_RCC_APB2_DIV_4 + * @arg @ref LL_RCC_APB2_DIV_8 + * @arg @ref LL_RCC_APB2_DIV_16 + */ +__STATIC_INLINE uint32_t LL_RCC_GetAPB2Prescaler(void) +{ + return (uint32_t)(READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2)); +} + +/** + * @brief Set Clock After Wake-Up From Stop mode + * @rmtoll CFGR STOPWUCK LL_RCC_SetClkAfterWakeFromStop + * @param Clock This parameter can be one of the following values: + * @arg @ref LL_RCC_STOP_WAKEUPCLOCK_MSI + * @arg @ref LL_RCC_STOP_WAKEUPCLOCK_HSI + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetClkAfterWakeFromStop(uint32_t Clock) +{ + MODIFY_REG(RCC->CFGR, RCC_CFGR_STOPWUCK, Clock); +} + +/** + * @brief Get Clock After Wake-Up From Stop mode + * @rmtoll CFGR STOPWUCK LL_RCC_GetClkAfterWakeFromStop + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_STOP_WAKEUPCLOCK_MSI + * @arg @ref LL_RCC_STOP_WAKEUPCLOCK_HSI + */ +__STATIC_INLINE uint32_t LL_RCC_GetClkAfterWakeFromStop(void) +{ + return (uint32_t)(READ_BIT(RCC->CFGR, RCC_CFGR_STOPWUCK)); +} + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_MCO MCO + * @{ + */ + +/** + * @brief Configure MCOx + * @rmtoll CFGR MCOSEL LL_RCC_ConfigMCO\n + * CFGR MCOPRE LL_RCC_ConfigMCO + * @param MCOxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_MCO1SOURCE_NOCLOCK + * @arg @ref LL_RCC_MCO1SOURCE_SYSCLK + * @arg @ref LL_RCC_MCO1SOURCE_MSI + * @arg @ref LL_RCC_MCO1SOURCE_HSI + * @arg @ref LL_RCC_MCO1SOURCE_HSE + * @arg @ref LL_RCC_MCO1SOURCE_HSI48 (*) + * @arg @ref LL_RCC_MCO1SOURCE_PLLCLK + * @arg @ref LL_RCC_MCO1SOURCE_LSI + * @arg @ref LL_RCC_MCO1SOURCE_LSE + * + * (*) value not defined in all devices. + * @param MCOxPrescaler This parameter can be one of the following values: + * @arg @ref LL_RCC_MCO1_DIV_1 + * @arg @ref LL_RCC_MCO1_DIV_2 + * @arg @ref LL_RCC_MCO1_DIV_4 + * @arg @ref LL_RCC_MCO1_DIV_8 + * @arg @ref LL_RCC_MCO1_DIV_16 + * @retval None + */ +__STATIC_INLINE void LL_RCC_ConfigMCO(uint32_t MCOxSource, uint32_t MCOxPrescaler) +{ + MODIFY_REG(RCC->CFGR, RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE, MCOxSource | MCOxPrescaler); +} + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_Peripheral_Clock_Source Peripheral Clock Source + * @{ + */ + +/** + * @brief Configure USARTx clock source + * @rmtoll CCIPR USARTxSEL LL_RCC_SetUSARTClockSource + * @param USARTxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_USART1_CLKSOURCE_PCLK2 + * @arg @ref LL_RCC_USART1_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_USART1_CLKSOURCE_HSI + * @arg @ref LL_RCC_USART1_CLKSOURCE_LSE + * @arg @ref LL_RCC_USART2_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_USART2_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_USART2_CLKSOURCE_HSI + * @arg @ref LL_RCC_USART2_CLKSOURCE_LSE + * @arg @ref LL_RCC_USART3_CLKSOURCE_PCLK1 (*) + * @arg @ref LL_RCC_USART3_CLKSOURCE_SYSCLK (*) + * @arg @ref LL_RCC_USART3_CLKSOURCE_HSI (*) + * @arg @ref LL_RCC_USART3_CLKSOURCE_LSE (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetUSARTClockSource(uint32_t USARTxSource) +{ + MODIFY_REG(RCC->CCIPR, (USARTxSource >> 16U), (USARTxSource & 0x0000FFFFU)); +} + +#if defined(UART4) || defined(UART5) +/** + * @brief Configure UARTx clock source + * @rmtoll CCIPR UARTxSEL LL_RCC_SetUARTClockSource + * @param UARTxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_UART4_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_UART4_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_UART4_CLKSOURCE_HSI + * @arg @ref LL_RCC_UART4_CLKSOURCE_LSE + * @arg @ref LL_RCC_UART5_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_UART5_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_UART5_CLKSOURCE_HSI + * @arg @ref LL_RCC_UART5_CLKSOURCE_LSE + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetUARTClockSource(uint32_t UARTxSource) +{ + MODIFY_REG(RCC->CCIPR, (UARTxSource >> 16U), (UARTxSource & 0x0000FFFFU)); +} +#endif /* UART4 || UART5 */ + +/** + * @brief Configure LPUART1x clock source + * @rmtoll CCIPR LPUART1SEL LL_RCC_SetLPUARTClockSource + * @param LPUARTxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_HSI + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_LSE + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetLPUARTClockSource(uint32_t LPUARTxSource) +{ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_LPUART1SEL, LPUARTxSource); +} + +/** + * @brief Configure I2Cx clock source + * @rmtoll CCIPR I2CxSEL LL_RCC_SetI2CClockSource + * @param I2CxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_I2C1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_I2C1_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_I2C1_CLKSOURCE_HSI + * @arg @ref LL_RCC_I2C2_CLKSOURCE_PCLK1 (*) + * @arg @ref LL_RCC_I2C2_CLKSOURCE_SYSCLK (*) + * @arg @ref LL_RCC_I2C2_CLKSOURCE_HSI (*) + * @arg @ref LL_RCC_I2C3_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_I2C3_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_I2C3_CLKSOURCE_HSI + * @arg @ref LL_RCC_I2C4_CLKSOURCE_PCLK1 (*) + * @arg @ref LL_RCC_I2C4_CLKSOURCE_SYSCLK (*) + * @arg @ref LL_RCC_I2C4_CLKSOURCE_HSI (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetI2CClockSource(uint32_t I2CxSource) +{ + __IO uint32_t *reg = (__IO uint32_t *)(uint32_t)(RCC_BASE + 0x88U + (I2CxSource >> 24U)); + MODIFY_REG(*reg, 3UL << ((I2CxSource & 0x001F0000U) >> 16U), ((I2CxSource & 0x000000FFU) << ((I2CxSource & 0x001F0000U) >> 16U))); +} + +/** + * @brief Configure LPTIMx clock source + * @rmtoll CCIPR LPTIMxSEL LL_RCC_SetLPTIMClockSource + * @param LPTIMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_LSI + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_HSI + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_LSE + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_LSI + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_HSI + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_LSE + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetLPTIMClockSource(uint32_t LPTIMxSource) +{ + MODIFY_REG(RCC->CCIPR, (LPTIMxSource & 0xFFFF0000U), (LPTIMxSource << 16U)); +} + +#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR2_SAI1SEL) +/** + * @brief Configure SAIx clock source + @if STM32L4S9xx + * @rmtoll CCIPR2 SAIxSEL LL_RCC_SetSAIClockSource + @else + * @rmtoll CCIPR SAIxSEL LL_RCC_SetSAIClockSource + @endif + * @param SAIxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PLLSAI1 + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PLLSAI2 (*) + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PLL + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PIN + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PLLSAI2 (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PLL (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PIN (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetSAIClockSource(uint32_t SAIxSource) +{ +#if defined(RCC_CCIPR2_SAI1SEL) + MODIFY_REG(RCC->CCIPR2, (SAIxSource >> 16U), (SAIxSource & 0x0000FFFFU)); +#else + MODIFY_REG(RCC->CCIPR, (SAIxSource & 0xFFFF0000U), (SAIxSource << 16U)); +#endif /* RCC_CCIPR2_SAI1SEL */ +} +#endif /* RCC_CCIPR_SAI1SEL || RCC_CCIPR2_SAI1SEL */ + +#if defined(RCC_CCIPR2_SDMMCSEL) +/** + * @brief Configure SDMMC1 kernel clock source + * @rmtoll CCIPR2 SDMMCSEL LL_RCC_SetSDMMCKernelClockSource + * @param SDMMCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE_48CLK (*) + * @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE_PLLP (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetSDMMCKernelClockSource(uint32_t SDMMCxSource) +{ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL, SDMMCxSource); +} +#endif /* RCC_CCIPR2_SDMMCSEL */ + +/** + * @brief Configure SDMMC1 clock source + * @rmtoll CCIPR CLK48SEL LL_RCC_SetSDMMCClockSource + * @param SDMMCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_NONE (*) + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_HSI48 (*) + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_PLL + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_MSI (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetSDMMCClockSource(uint32_t SDMMCxSource) +{ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, SDMMCxSource); +} + +/** + * @brief Configure RNG clock source + * @rmtoll CCIPR CLK48SEL LL_RCC_SetRNGClockSource + * @param RNGxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_RNG_CLKSOURCE_NONE (*) + * @arg @ref LL_RCC_RNG_CLKSOURCE_HSI48 (*) + * @arg @ref LL_RCC_RNG_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_RNG_CLKSOURCE_PLL + * @arg @ref LL_RCC_RNG_CLKSOURCE_MSI + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetRNGClockSource(uint32_t RNGxSource) +{ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, RNGxSource); +} + +#if defined(USB_OTG_FS) || defined(USB) +/** + * @brief Configure USB clock source + * @rmtoll CCIPR CLK48SEL LL_RCC_SetUSBClockSource + * @param USBxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_USB_CLKSOURCE_NONE (*) + * @arg @ref LL_RCC_USB_CLKSOURCE_HSI48 (*) + * @arg @ref LL_RCC_USB_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_USB_CLKSOURCE_PLL + * @arg @ref LL_RCC_USB_CLKSOURCE_MSI + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetUSBClockSource(uint32_t USBxSource) +{ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_CLK48SEL, USBxSource); +} +#endif /* USB_OTG_FS || USB */ + +#if defined(RCC_CCIPR_ADCSEL) +/** + * @brief Configure ADC clock source + * @rmtoll CCIPR ADCSEL LL_RCC_SetADCClockSource + * @param ADCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_ADC_CLKSOURCE_NONE + * @arg @ref LL_RCC_ADC_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_ADC_CLKSOURCE_PLLSAI2 (*) + * @arg @ref LL_RCC_ADC_CLKSOURCE_SYSCLK + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetADCClockSource(uint32_t ADCxSource) +{ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_ADCSEL, ADCxSource); +} +#endif /* RCC_CCIPR_ADCSEL */ + +#if defined(SWPMI1) +/** + * @brief Configure SWPMI clock source + * @rmtoll CCIPR SWPMI1SEL LL_RCC_SetSWPMIClockSource + * @param SWPMIxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SWPMI1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_SWPMI1_CLKSOURCE_HSI + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetSWPMIClockSource(uint32_t SWPMIxSource) +{ + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_SWPMI1SEL, SWPMIxSource); +} +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Channel0) +#if defined(RCC_CCIPR2_ADFSDM1SEL) +/** + * @brief Configure DFSDM Audio clock source + * @rmtoll CCIPR2 ADFSDM1SEL LL_RCC_SetDFSDMAudioClockSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE_SAI1 + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE_HSI + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE_MSI + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetDFSDMAudioClockSource(uint32_t Source) +{ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_ADFSDM1SEL, Source); +} +#endif /* RCC_CCIPR2_ADFSDM1SEL */ + +/** + * @brief Configure DFSDM Kernel clock source + @if STM32L4S9xx + * @rmtoll CCIPR2 DFSDM1SEL LL_RCC_SetDFSDMClockSource + @else + * @rmtoll CCIPR DFSDM1SEL LL_RCC_SetDFSDMClockSource + @endif + * @param DFSDMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_CLKSOURCE_PCLK2 + * @arg @ref LL_RCC_DFSDM1_CLKSOURCE_SYSCLK + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetDFSDMClockSource(uint32_t DFSDMxSource) +{ +#if defined(RCC_CCIPR2_DFSDM1SEL) + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_DFSDM1SEL, DFSDMxSource); +#else + MODIFY_REG(RCC->CCIPR, RCC_CCIPR_DFSDM1SEL, DFSDMxSource); +#endif /* RCC_CCIPR2_DFSDM1SEL */ +} +#endif /* DFSDM1_Channel0 */ + +#if defined(DSI) +/** + * @brief Configure DSI clock source + * @rmtoll CCIPR2 DSISEL LL_RCC_SetDSIClockSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_DSI_CLKSOURCE_PHY + * @arg @ref LL_RCC_DSI_CLKSOURCE_PLL + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetDSIClockSource(uint32_t Source) +{ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_DSISEL, Source); +} +#endif /* DSI */ + +#if defined(LTDC) +/** + * @brief Configure LTDC Clock Source + * @rmtoll CCIPR2 PLLSAI2DIVR LL_RCC_SetLTDCClockSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV2 + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV4 + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV8 + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV16 + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetLTDCClockSource(uint32_t Source) +{ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR, Source); +} +#endif /* LTDC */ + +#if defined(OCTOSPI1) +/** + * @brief Configure OCTOSPI clock source + * @rmtoll CCIPR2 OSPISEL LL_RCC_SetOCTOSPIClockSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE_MSI + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE_PLL + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetOCTOSPIClockSource(uint32_t Source) +{ + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_OSPISEL, Source); +} +#endif /* OCTOSPI1 */ + +/** + * @brief Get USARTx clock source + * @rmtoll CCIPR USARTxSEL LL_RCC_GetUSARTClockSource + * @param USARTx This parameter can be one of the following values: + * @arg @ref LL_RCC_USART1_CLKSOURCE + * @arg @ref LL_RCC_USART2_CLKSOURCE + * @arg @ref LL_RCC_USART3_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_USART1_CLKSOURCE_PCLK2 + * @arg @ref LL_RCC_USART1_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_USART1_CLKSOURCE_HSI + * @arg @ref LL_RCC_USART1_CLKSOURCE_LSE + * @arg @ref LL_RCC_USART2_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_USART2_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_USART2_CLKSOURCE_HSI + * @arg @ref LL_RCC_USART2_CLKSOURCE_LSE + * @arg @ref LL_RCC_USART3_CLKSOURCE_PCLK1 (*) + * @arg @ref LL_RCC_USART3_CLKSOURCE_SYSCLK (*) + * @arg @ref LL_RCC_USART3_CLKSOURCE_HSI (*) + * @arg @ref LL_RCC_USART3_CLKSOURCE_LSE (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetUSARTClockSource(uint32_t USARTx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, USARTx) | (USARTx << 16U)); +} + +#if defined(UART4) || defined(UART5) +/** + * @brief Get UARTx clock source + * @rmtoll CCIPR UARTxSEL LL_RCC_GetUARTClockSource + * @param UARTx This parameter can be one of the following values: + * @arg @ref LL_RCC_UART4_CLKSOURCE + * @arg @ref LL_RCC_UART5_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_UART4_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_UART4_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_UART4_CLKSOURCE_HSI + * @arg @ref LL_RCC_UART4_CLKSOURCE_LSE + * @arg @ref LL_RCC_UART5_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_UART5_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_UART5_CLKSOURCE_HSI + * @arg @ref LL_RCC_UART5_CLKSOURCE_LSE + */ +__STATIC_INLINE uint32_t LL_RCC_GetUARTClockSource(uint32_t UARTx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, UARTx) | (UARTx << 16U)); +} +#endif /* UART4 || UART5 */ + +/** + * @brief Get LPUARTx clock source + * @rmtoll CCIPR LPUART1SEL LL_RCC_GetLPUARTClockSource + * @param LPUARTx This parameter can be one of the following values: + * @arg @ref LL_RCC_LPUART1_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_HSI + * @arg @ref LL_RCC_LPUART1_CLKSOURCE_LSE + */ +__STATIC_INLINE uint32_t LL_RCC_GetLPUARTClockSource(uint32_t LPUARTx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, LPUARTx)); +} + +/** + * @brief Get I2Cx clock source + * @rmtoll CCIPR I2CxSEL LL_RCC_GetI2CClockSource + * @param I2Cx This parameter can be one of the following values: + * @arg @ref LL_RCC_I2C1_CLKSOURCE + * @arg @ref LL_RCC_I2C2_CLKSOURCE (*) + * @arg @ref LL_RCC_I2C3_CLKSOURCE + * @arg @ref LL_RCC_I2C4_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_I2C1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_I2C1_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_I2C1_CLKSOURCE_HSI + * @arg @ref LL_RCC_I2C2_CLKSOURCE_PCLK1 (*) + * @arg @ref LL_RCC_I2C2_CLKSOURCE_SYSCLK (*) + * @arg @ref LL_RCC_I2C2_CLKSOURCE_HSI (*) + * @arg @ref LL_RCC_I2C3_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_I2C3_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_I2C3_CLKSOURCE_HSI + * @arg @ref LL_RCC_I2C4_CLKSOURCE_PCLK1 (*) + * @arg @ref LL_RCC_I2C4_CLKSOURCE_SYSCLK (*) + * @arg @ref LL_RCC_I2C4_CLKSOURCE_HSI (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetI2CClockSource(uint32_t I2Cx) +{ + __IO const uint32_t *reg = (__IO uint32_t *)(uint32_t)(RCC_BASE + 0x88U + (I2Cx >> 24U)); + return (uint32_t)((READ_BIT(*reg, 3UL << ((I2Cx & 0x001F0000U) >> 16U)) >> ((I2Cx & 0x001F0000U) >> 16U)) | (I2Cx & 0xFFFF0000U)); +} + +/** + * @brief Get LPTIMx clock source + * @rmtoll CCIPR LPTIMxSEL LL_RCC_GetLPTIMClockSource + * @param LPTIMx This parameter can be one of the following values: + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_LSI + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_HSI + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE_LSE + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_LSI + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_HSI + * @arg @ref LL_RCC_LPTIM2_CLKSOURCE_LSE + */ +__STATIC_INLINE uint32_t LL_RCC_GetLPTIMClockSource(uint32_t LPTIMx) +{ + return (uint32_t)((READ_BIT(RCC->CCIPR, LPTIMx) >> 16U) | LPTIMx); +} + +#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR2_SAI1SEL) +/** + * @brief Get SAIx clock source + @if STM32L4S9xx + * @rmtoll CCIPR2 SAIxSEL LL_RCC_GetSAIClockSource + @else + * @rmtoll CCIPR SAIxSEL LL_RCC_GetSAIClockSource + @endif + * @param SAIx This parameter can be one of the following values: + * @arg @ref LL_RCC_SAI1_CLKSOURCE + * @arg @ref LL_RCC_SAI2_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PLLSAI1 + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PLLSAI2 (*) + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PLL + * @arg @ref LL_RCC_SAI1_CLKSOURCE_PIN + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PLLSAI2 (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PLL (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE_PIN (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetSAIClockSource(uint32_t SAIx) +{ +#if defined(RCC_CCIPR2_SAI1SEL) + return (uint32_t)(READ_BIT(RCC->CCIPR2, SAIx) | (SAIx << 16U)); +#else + return (uint32_t)(READ_BIT(RCC->CCIPR, SAIx) >> 16U | SAIx); +#endif /* RCC_CCIPR2_SAI1SEL */ +} +#endif /* RCC_CCIPR_SAI1SEL || RCC_CCIPR2_SAI1SEL */ + +#if defined(SDMMC1) +#if defined(RCC_CCIPR2_SDMMCSEL) +/** + * @brief Get SDMMCx kernel clock source + * @rmtoll CCIPR2 SDMMCSEL LL_RCC_GetSDMMCKernelClockSource + * @param SDMMCx This parameter can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE_48CLK (*) + * @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE_PLL (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetSDMMCKernelClockSource(uint32_t SDMMCx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR2, SDMMCx)); +} +#endif /* RCC_CCIPR2_SDMMCSEL */ + +/** + * @brief Get SDMMCx clock source + * @rmtoll CCIPR CLK48SEL LL_RCC_GetSDMMCClockSource + * @param SDMMCx This parameter can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_NONE (*) + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_HSI48 (*) + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_PLL + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE_MSI (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetSDMMCClockSource(uint32_t SDMMCx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, SDMMCx)); +} +#endif /* SDMMC1 */ + +/** + * @brief Get RNGx clock source + * @rmtoll CCIPR CLK48SEL LL_RCC_GetRNGClockSource + * @param RNGx This parameter can be one of the following values: + * @arg @ref LL_RCC_RNG_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_RNG_CLKSOURCE_NONE (*) + * @arg @ref LL_RCC_RNG_CLKSOURCE_HSI48 (*) + * @arg @ref LL_RCC_RNG_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_RNG_CLKSOURCE_PLL + * @arg @ref LL_RCC_RNG_CLKSOURCE_MSI + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetRNGClockSource(uint32_t RNGx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, RNGx)); +} + +#if defined(USB_OTG_FS) || defined(USB) +/** + * @brief Get USBx clock source + * @rmtoll CCIPR CLK48SEL LL_RCC_GetUSBClockSource + * @param USBx This parameter can be one of the following values: + * @arg @ref LL_RCC_USB_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_USB_CLKSOURCE_NONE (*) + * @arg @ref LL_RCC_USB_CLKSOURCE_HSI48 (*) + * @arg @ref LL_RCC_USB_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_USB_CLKSOURCE_PLL + * @arg @ref LL_RCC_USB_CLKSOURCE_MSI + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetUSBClockSource(uint32_t USBx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, USBx)); +} +#endif /* USB_OTG_FS || USB */ + +/** + * @brief Get ADCx clock source + * @rmtoll CCIPR ADCSEL LL_RCC_GetADCClockSource + * @param ADCx This parameter can be one of the following values: + * @arg @ref LL_RCC_ADC_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_ADC_CLKSOURCE_NONE + * @arg @ref LL_RCC_ADC_CLKSOURCE_PLLSAI1 (*) + * @arg @ref LL_RCC_ADC_CLKSOURCE_PLLSAI2 (*) + * @arg @ref LL_RCC_ADC_CLKSOURCE_SYSCLK + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_GetADCClockSource(uint32_t ADCx) +{ +#if defined(RCC_CCIPR_ADCSEL) + return (uint32_t)(READ_BIT(RCC->CCIPR, ADCx)); +#else + (void)ADCx; /* unused */ + return ((READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADCEN) != 0U) ? LL_RCC_ADC_CLKSOURCE_SYSCLK : LL_RCC_ADC_CLKSOURCE_NONE); +#endif /* RCC_CCIPR_ADCSEL */ +} + +#if defined(SWPMI1) +/** + * @brief Get SWPMIx clock source + * @rmtoll CCIPR SWPMI1SEL LL_RCC_GetSWPMIClockSource + * @param SPWMIx This parameter can be one of the following values: + * @arg @ref LL_RCC_SWPMI1_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_SWPMI1_CLKSOURCE_PCLK1 + * @arg @ref LL_RCC_SWPMI1_CLKSOURCE_HSI + */ +__STATIC_INLINE uint32_t LL_RCC_GetSWPMIClockSource(uint32_t SPWMIx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR, SPWMIx)); +} +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Channel0) +#if defined(RCC_CCIPR2_ADFSDM1SEL) +/** + * @brief Get DFSDM Audio Clock Source + * @rmtoll CCIPR2 ADFSDM1SEL LL_RCC_GetDFSDMAudioClockSource + * @param DFSDMx This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE_SAI1 + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE_HSI + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE_MSI + */ +__STATIC_INLINE uint32_t LL_RCC_GetDFSDMAudioClockSource(uint32_t DFSDMx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR2, DFSDMx)); +} +#endif /* RCC_CCIPR2_ADFSDM1SEL */ + +/** + * @brief Get DFSDMx Kernel clock source + @if STM32L4S9xx + * @rmtoll CCIPR2 DFSDM1SEL LL_RCC_GetDFSDMClockSource + @else + * @rmtoll CCIPR DFSDM1SEL LL_RCC_GetDFSDMClockSource + @endif + * @param DFSDMx This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_CLKSOURCE_PCLK2 + * @arg @ref LL_RCC_DFSDM1_CLKSOURCE_SYSCLK + */ +__STATIC_INLINE uint32_t LL_RCC_GetDFSDMClockSource(uint32_t DFSDMx) +{ +#if defined(RCC_CCIPR2_DFSDM1SEL) + return (uint32_t)(READ_BIT(RCC->CCIPR2, DFSDMx)); +#else + return (uint32_t)(READ_BIT(RCC->CCIPR, DFSDMx)); +#endif /* RCC_CCIPR2_DFSDM1SEL */ +} +#endif /* DFSDM1_Channel0 */ + +#if defined(DSI) +/** + * @brief Get DSI Clock Source + * @rmtoll CCIPR2 DSISEL LL_RCC_GetDSIClockSource + * @param DSIx This parameter can be one of the following values: + * @arg @ref LL_RCC_DSI_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_DSI_CLKSOURCE_PHY + * @arg @ref LL_RCC_DSI_CLKSOURCE_PLL + */ +__STATIC_INLINE uint32_t LL_RCC_GetDSIClockSource(uint32_t DSIx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR2, DSIx)); +} +#endif /* DSI */ + +#if defined(LTDC) +/** + * @brief Get LTDC Clock Source + * @rmtoll CCIPR2 PLLSAI2DIVR LL_RCC_GetLTDCClockSource + * @param LTDCx This parameter can be one of the following values: + * @arg @ref LL_RCC_LTDC_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV2 + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV4 + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV8 + * @arg @ref LL_RCC_LTDC_CLKSOURCE_PLLSAI2R_DIV16 + */ +__STATIC_INLINE uint32_t LL_RCC_GetLTDCClockSource(uint32_t LTDCx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR2, LTDCx)); +} +#endif /* LTDC */ + +#if defined(OCTOSPI1) +/** + * @brief Get OCTOSPI clock source + * @rmtoll CCIPR2 OSPISEL LL_RCC_GetOCTOSPIClockSource + * @param OCTOSPIx This parameter can be one of the following values: + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE_SYSCLK + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE_MSI + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE_PLL + */ +__STATIC_INLINE uint32_t LL_RCC_GetOCTOSPIClockSource(uint32_t OCTOSPIx) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR2, OCTOSPIx)); +} +#endif /* OCTOSPI1 */ +/** + * @} + */ + +/** @defgroup RCC_LL_EF_RTC RTC + * @{ + */ + +/** + * @brief Set RTC Clock Source + * @note Once the RTC clock source has been selected, it cannot be changed anymore unless + * the Backup domain is reset, or unless a failure is detected on LSE (LSECSSD is + * set). The BDRST bit can be used to reset them. + * @rmtoll BDCR RTCSEL LL_RCC_SetRTCClockSource + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_RTC_CLKSOURCE_NONE + * @arg @ref LL_RCC_RTC_CLKSOURCE_LSE + * @arg @ref LL_RCC_RTC_CLKSOURCE_LSI + * @arg @ref LL_RCC_RTC_CLKSOURCE_HSE_DIV32 + * @retval None + */ +__STATIC_INLINE void LL_RCC_SetRTCClockSource(uint32_t Source) +{ + MODIFY_REG(RCC->BDCR, RCC_BDCR_RTCSEL, Source); +} + +/** + * @brief Get RTC Clock Source + * @rmtoll BDCR RTCSEL LL_RCC_GetRTCClockSource + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_RTC_CLKSOURCE_NONE + * @arg @ref LL_RCC_RTC_CLKSOURCE_LSE + * @arg @ref LL_RCC_RTC_CLKSOURCE_LSI + * @arg @ref LL_RCC_RTC_CLKSOURCE_HSE_DIV32 + */ +__STATIC_INLINE uint32_t LL_RCC_GetRTCClockSource(void) +{ + return (uint32_t)(READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)); +} + +/** + * @brief Enable RTC + * @rmtoll BDCR RTCEN LL_RCC_EnableRTC + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableRTC(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN); +} + +/** + * @brief Disable RTC + * @rmtoll BDCR RTCEN LL_RCC_DisableRTC + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableRTC(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_RTCEN); +} + +/** + * @brief Check if RTC has been enabled or not + * @rmtoll BDCR RTCEN LL_RCC_IsEnabledRTC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledRTC(void) +{ + return ((READ_BIT(RCC->BDCR, RCC_BDCR_RTCEN) == RCC_BDCR_RTCEN) ? 1UL : 0UL); +} + +/** + * @brief Force the Backup domain reset + * @rmtoll BDCR BDRST LL_RCC_ForceBackupDomainReset + * @retval None + */ +__STATIC_INLINE void LL_RCC_ForceBackupDomainReset(void) +{ + SET_BIT(RCC->BDCR, RCC_BDCR_BDRST); +} + +/** + * @brief Release the Backup domain reset + * @rmtoll BDCR BDRST LL_RCC_ReleaseBackupDomainReset + * @retval None + */ +__STATIC_INLINE void LL_RCC_ReleaseBackupDomainReset(void) +{ + CLEAR_BIT(RCC->BDCR, RCC_BDCR_BDRST); +} + +/** + * @} + */ + + +/** @defgroup RCC_LL_EF_PLL PLL + * @{ + */ + +/** + * @brief Enable PLL + * @rmtoll CR PLLON LL_RCC_PLL_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_Enable(void) +{ + SET_BIT(RCC->CR, RCC_CR_PLLON); +} + +/** + * @brief Disable PLL + * @note Cannot be disabled if the PLL clock is used as the system clock + * @rmtoll CR PLLON LL_RCC_PLL_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_Disable(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_PLLON); +} + +/** + * @brief Check if PLL Ready + * @rmtoll CR PLLRDY LL_RCC_PLL_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_IsReady(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RCC_CR_PLLRDY) ? 1UL : 0UL); +} + +/** + * @brief Configure PLL used for SYSCLK Domain + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLN/PLLR can be written only when PLL is disabled. + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLL_ConfigDomain_SYS\n + * PLLCFGR PLLM LL_RCC_PLL_ConfigDomain_SYS\n + * PLLCFGR PLLN LL_RCC_PLL_ConfigDomain_SYS\n + * PLLCFGR PLLR LL_RCC_PLL_ConfigDomain_SYS + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLR This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLR_DIV_2 + * @arg @ref LL_RCC_PLLR_DIV_4 + * @arg @ref LL_RCC_PLLR_DIV_6 + * @arg @ref LL_RCC_PLLR_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_ConfigDomain_SYS(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLR, + Source | PLLM | (PLLN << RCC_PLLCFGR_PLLN_Pos) | PLLR); +} + +#if defined(RCC_PLLP_SUPPORT) +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +/** + * @brief Configure PLL used for SAI domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLN/PLLP can be written only when PLL is disabled. + * @note This can be selected for SAI1 or SAI2 (*) + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLL_ConfigDomain_SAI\n + * PLLCFGR PLLM LL_RCC_PLL_ConfigDomain_SAI\n + * PLLCFGR PLLN LL_RCC_PLL_ConfigDomain_SAI\n + * PLLCFGR PLLPDIV LL_RCC_PLL_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLP_DIV_2 + * @arg @ref LL_RCC_PLLP_DIV_3 + * @arg @ref LL_RCC_PLLP_DIV_4 + * @arg @ref LL_RCC_PLLP_DIV_5 + * @arg @ref LL_RCC_PLLP_DIV_6 + * @arg @ref LL_RCC_PLLP_DIV_7 + * @arg @ref LL_RCC_PLLP_DIV_8 + * @arg @ref LL_RCC_PLLP_DIV_9 + * @arg @ref LL_RCC_PLLP_DIV_10 + * @arg @ref LL_RCC_PLLP_DIV_11 + * @arg @ref LL_RCC_PLLP_DIV_12 + * @arg @ref LL_RCC_PLLP_DIV_13 + * @arg @ref LL_RCC_PLLP_DIV_14 + * @arg @ref LL_RCC_PLLP_DIV_15 + * @arg @ref LL_RCC_PLLP_DIV_16 + * @arg @ref LL_RCC_PLLP_DIV_17 + * @arg @ref LL_RCC_PLLP_DIV_18 + * @arg @ref LL_RCC_PLLP_DIV_19 + * @arg @ref LL_RCC_PLLP_DIV_20 + * @arg @ref LL_RCC_PLLP_DIV_21 + * @arg @ref LL_RCC_PLLP_DIV_22 + * @arg @ref LL_RCC_PLLP_DIV_23 + * @arg @ref LL_RCC_PLLP_DIV_24 + * @arg @ref LL_RCC_PLLP_DIV_25 + * @arg @ref LL_RCC_PLLP_DIV_26 + * @arg @ref LL_RCC_PLLP_DIV_27 + * @arg @ref LL_RCC_PLLP_DIV_28 + * @arg @ref LL_RCC_PLLP_DIV_29 + * @arg @ref LL_RCC_PLLP_DIV_30 + * @arg @ref LL_RCC_PLLP_DIV_31 + * @retval None + */ +#else +/** + * @brief Configure PLL used for SAI domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLN/PLLP can be written only when PLL is disabled. + * @note This can be selected for SAI1 or SAI2 (*) + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLL_ConfigDomain_SAI\n + * PLLCFGR PLLM LL_RCC_PLL_ConfigDomain_SAI\n + * PLLCFGR PLLN LL_RCC_PLL_ConfigDomain_SAI\n + * PLLCFGR PLLP LL_RCC_PLL_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLP_DIV_7 + * @arg @ref LL_RCC_PLLP_DIV_17 + * @retval None + */ +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +__STATIC_INLINE void LL_RCC_PLL_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLPDIV, + Source | PLLM | (PLLN << RCC_PLLCFGR_PLLN_Pos) | PLLP); +#else + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLP, + Source | PLLM | (PLLN << RCC_PLLCFGR_PLLN_Pos) | PLLP); +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +} +#endif /* RCC_PLLP_SUPPORT */ + +/** + * @brief Configure PLL used for 48Mhz domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLN/PLLQ can be written only when PLL is disabled. + * @note This can be selected for USB, RNG, SDMMC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLL_ConfigDomain_48M\n + * PLLCFGR PLLM LL_RCC_PLL_ConfigDomain_48M\n + * PLLCFGR PLLN LL_RCC_PLL_ConfigDomain_48M\n + * PLLCFGR PLLQ LL_RCC_PLL_ConfigDomain_48M + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLQ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLQ_DIV_2 + * @arg @ref LL_RCC_PLLQ_DIV_4 + * @arg @ref LL_RCC_PLLQ_DIV_6 + * @arg @ref LL_RCC_PLLQ_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_ConfigDomain_48M(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLQ) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLQ, + Source | PLLM | (PLLN << RCC_PLLCFGR_PLLN_Pos) | PLLQ); +} + +/** + * @brief Configure PLL clock source + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLL_SetMainSource + * @param PLLSource This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_SetMainSource(uint32_t PLLSource) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PLLSource); +} + +/** + * @brief Get the oscillator used as PLL clock source. + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLL_GetMainSource + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetMainSource(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC)); +} + +/** + * @brief Get Main PLL multiplication factor for VCO + * @rmtoll PLLCFGR PLLN LL_RCC_PLL_GetN + * @retval Between 8 and 86 or 127 depending on devices + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetN(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos); +} + +#if defined(RCC_PLLP_SUPPORT) +#if defined(RCC_PLLP_DIV_2_31_SUPPORT) +/** + * @brief Get Main PLL division factor for PLLP + * @note Used for PLLSAI3CLK (SAI1 and SAI2 clock) + * @rmtoll PLLCFGR PLLPDIV LL_RCC_PLL_GetP + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLP_DIV_2 + * @arg @ref LL_RCC_PLLP_DIV_3 + * @arg @ref LL_RCC_PLLP_DIV_4 + * @arg @ref LL_RCC_PLLP_DIV_5 + * @arg @ref LL_RCC_PLLP_DIV_6 + * @arg @ref LL_RCC_PLLP_DIV_7 + * @arg @ref LL_RCC_PLLP_DIV_8 + * @arg @ref LL_RCC_PLLP_DIV_9 + * @arg @ref LL_RCC_PLLP_DIV_10 + * @arg @ref LL_RCC_PLLP_DIV_11 + * @arg @ref LL_RCC_PLLP_DIV_12 + * @arg @ref LL_RCC_PLLP_DIV_13 + * @arg @ref LL_RCC_PLLP_DIV_14 + * @arg @ref LL_RCC_PLLP_DIV_15 + * @arg @ref LL_RCC_PLLP_DIV_16 + * @arg @ref LL_RCC_PLLP_DIV_17 + * @arg @ref LL_RCC_PLLP_DIV_18 + * @arg @ref LL_RCC_PLLP_DIV_19 + * @arg @ref LL_RCC_PLLP_DIV_20 + * @arg @ref LL_RCC_PLLP_DIV_21 + * @arg @ref LL_RCC_PLLP_DIV_22 + * @arg @ref LL_RCC_PLLP_DIV_23 + * @arg @ref LL_RCC_PLLP_DIV_24 + * @arg @ref LL_RCC_PLLP_DIV_25 + * @arg @ref LL_RCC_PLLP_DIV_26 + * @arg @ref LL_RCC_PLLP_DIV_27 + * @arg @ref LL_RCC_PLLP_DIV_28 + * @arg @ref LL_RCC_PLLP_DIV_29 + * @arg @ref LL_RCC_PLLP_DIV_30 + * @arg @ref LL_RCC_PLLP_DIV_31 + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetP(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV)); +} +#else +/** + * @brief Get Main PLL division factor for PLLP + * @note Used for PLLSAI3CLK (SAI1 and SAI2 clock) + * @rmtoll PLLCFGR PLLP LL_RCC_PLL_GetP + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLP_DIV_7 + * @arg @ref LL_RCC_PLLP_DIV_17 + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetP(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP)); +} +#endif /* RCC_PLLP_DIV_2_31_SUPPORT */ +#endif /* RCC_PLLP_SUPPORT */ + +/** + * @brief Get Main PLL division factor for PLLQ + * @note Used for PLL48M1CLK selected for USB, RNG, SDMMC (48 MHz clock) + * @rmtoll PLLCFGR PLLQ LL_RCC_PLL_GetQ + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLQ_DIV_2 + * @arg @ref LL_RCC_PLLQ_DIV_4 + * @arg @ref LL_RCC_PLLQ_DIV_6 + * @arg @ref LL_RCC_PLLQ_DIV_8 + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetQ(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ)); +} + +/** + * @brief Get Main PLL division factor for PLLR + * @note Used for PLLCLK (system clock) + * @rmtoll PLLCFGR PLLR LL_RCC_PLL_GetR + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLR_DIV_2 + * @arg @ref LL_RCC_PLLR_DIV_4 + * @arg @ref LL_RCC_PLLR_DIV_6 + * @arg @ref LL_RCC_PLLR_DIV_8 + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetR(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR)); +} + +/** + * @brief Get Division factor for the main PLL and other PLL + * @rmtoll PLLCFGR PLLM LL_RCC_PLL_GetDivider + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @arg @ref LL_RCC_PLLM_DIV_9 (*) + * @arg @ref LL_RCC_PLLM_DIV_10 (*) + * @arg @ref LL_RCC_PLLM_DIV_11 (*) + * @arg @ref LL_RCC_PLLM_DIV_12 (*) + * @arg @ref LL_RCC_PLLM_DIV_13 (*) + * @arg @ref LL_RCC_PLLM_DIV_14 (*) + * @arg @ref LL_RCC_PLLM_DIV_15 (*) + * @arg @ref LL_RCC_PLLM_DIV_16 (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_GetDivider(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM)); +} + +#if defined(RCC_PLLP_SUPPORT) +/** + * @brief Enable PLL output mapped on SAI domain clock + * @rmtoll PLLCFGR PLLPEN LL_RCC_PLL_EnableDomain_SAI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_EnableDomain_SAI(void) +{ + SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN); +} + +/** + * @brief Disable PLL output mapped on SAI domain clock + * @note Cannot be disabled if the PLL clock is used as the system + * clock + * @note In order to save power, when the PLLCLK of the PLL is + * not used, should be 0 + * @rmtoll PLLCFGR PLLPEN LL_RCC_PLL_DisableDomain_SAI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_DisableDomain_SAI(void) +{ + CLEAR_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN); +} + +/** + * @brief Check if PLL output mapped on SAI domain clock is enabled + * @rmtoll PLLCFGR PLLPEN LL_RCC_PLL_IsEnabledDomain_SAI + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_IsEnabledDomain_SAI(void) +{ + return ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN) == (RCC_PLLCFGR_PLLPEN)) ? 1UL : 0UL); +} + +#endif /* RCC_PLLP_SUPPORT */ + +/** + * @brief Enable PLL output mapped on 48MHz domain clock + * @rmtoll PLLCFGR PLLQEN LL_RCC_PLL_EnableDomain_48M + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_EnableDomain_48M(void) +{ + SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN); +} + +/** + * @brief Disable PLL output mapped on 48MHz domain clock + * @note Cannot be disabled if the PLL clock is used as the system + * clock + * @note In order to save power, when the PLLCLK of the PLL is + * not used, should be 0 + * @rmtoll PLLCFGR PLLQEN LL_RCC_PLL_DisableDomain_48M + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_DisableDomain_48M(void) +{ + CLEAR_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN); +} + +/** + * @brief Check if PLL output mapped on 48MHz domain clock is enabled + * @rmtoll PLLCFGR PLLQEN LL_RCC_PLL_IsEnabledDomain_48M + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_IsEnabledDomain_48M(void) +{ + return ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN) == (RCC_PLLCFGR_PLLQEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable PLL output mapped on SYSCLK domain + * @rmtoll PLLCFGR PLLREN LL_RCC_PLL_EnableDomain_SYS + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_EnableDomain_SYS(void) +{ + SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLREN); +} + +/** + * @brief Disable PLL output mapped on SYSCLK domain + * @note Cannot be disabled if the PLL clock is used as the system + * clock + * @note In order to save power, when the PLLCLK of the PLL is + * not used, Main PLL should be 0 + * @rmtoll PLLCFGR PLLREN LL_RCC_PLL_DisableDomain_SYS + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLL_DisableDomain_SYS(void) +{ + CLEAR_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLREN); +} + +/** + * @brief Check if PLL output mapped on SYSCLK domain clock is enabled + * @rmtoll PLLCFGR PLLREN LL_RCC_PLL_IsEnabledDomain_SYS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLL_IsEnabledDomain_SYS(void) +{ + return ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLREN) == (RCC_PLLCFGR_PLLREN)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** @defgroup RCC_LL_EF_PLLSAI1 PLLSAI1 + * @{ + */ + +/** + * @brief Enable PLLSAI1 + * @rmtoll CR PLLSAI1ON LL_RCC_PLLSAI1_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_Enable(void) +{ + SET_BIT(RCC->CR, RCC_CR_PLLSAI1ON); +} + +/** + * @brief Disable PLLSAI1 + * @rmtoll CR PLLSAI1ON LL_RCC_PLLSAI1_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_Disable(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_PLLSAI1ON); +} + +/** + * @brief Check if PLLSAI1 Ready + * @rmtoll CR PLLSAI1RDY LL_RCC_PLLSAI1_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_IsReady(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RCC_CR_PLLSAI1RDY) ? 1UL : 0UL); +} + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +/** + * @brief Configure PLLSAI1 used for 48Mhz domain clock + * @note PLL Source can be written only when PLL, PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI1M/PLLSAI1N/PLLSAI1Q can be written only when PLLSAI1 is disabled. + * @note This can be selected for USB, RNG, SDMMC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_48M\n + * PLLSAI1CFGR PLLSAI1M LL_RCC_PLLSAI1_ConfigDomain_48M\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_48M\n + * PLLSAI1CFGR PLLSAI1Q LL_RCC_PLLSAI1_ConfigDomain_48M + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLQ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_48M(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLQ) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, Source); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M | RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q, + PLLM | (PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | PLLQ); +} +#else +/** + * @brief Configure PLLSAI1 used for 48Mhz domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI1N/PLLSAI1Q can be written only when PLLSAI1 is disabled. + * @note This can be selected for USB, RNG, SDMMC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_48M\n + * PLLCFGR PLLM LL_RCC_PLLSAI1_ConfigDomain_48M\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_48M\n + * PLLSAI1CFGR PLLSAI1Q LL_RCC_PLLSAI1_ConfigDomain_48M + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLQ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_48M(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLQ) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q, PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos | PLLQ); +} +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +/** + * @brief Configure PLLSAI1 used for SAI domain clock + * @note PLL Source can be written only when PLL, PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI1M/PLLSAI1N/PLLSAI1PDIV can be written only when PLLSAI1 is disabled. + * @note This can be selected for SAI1 or SAI2 + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1M LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1PDIV LL_RCC_PLLSAI1_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_2 + * @arg @ref LL_RCC_PLLSAI1P_DIV_3 + * @arg @ref LL_RCC_PLLSAI1P_DIV_4 + * @arg @ref LL_RCC_PLLSAI1P_DIV_5 + * @arg @ref LL_RCC_PLLSAI1P_DIV_6 + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_8 + * @arg @ref LL_RCC_PLLSAI1P_DIV_9 + * @arg @ref LL_RCC_PLLSAI1P_DIV_10 + * @arg @ref LL_RCC_PLLSAI1P_DIV_11 + * @arg @ref LL_RCC_PLLSAI1P_DIV_12 + * @arg @ref LL_RCC_PLLSAI1P_DIV_13 + * @arg @ref LL_RCC_PLLSAI1P_DIV_14 + * @arg @ref LL_RCC_PLLSAI1P_DIV_15 + * @arg @ref LL_RCC_PLLSAI1P_DIV_16 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @arg @ref LL_RCC_PLLSAI1P_DIV_18 + * @arg @ref LL_RCC_PLLSAI1P_DIV_19 + * @arg @ref LL_RCC_PLLSAI1P_DIV_20 + * @arg @ref LL_RCC_PLLSAI1P_DIV_21 + * @arg @ref LL_RCC_PLLSAI1P_DIV_22 + * @arg @ref LL_RCC_PLLSAI1P_DIV_23 + * @arg @ref LL_RCC_PLLSAI1P_DIV_24 + * @arg @ref LL_RCC_PLLSAI1P_DIV_25 + * @arg @ref LL_RCC_PLLSAI1P_DIV_26 + * @arg @ref LL_RCC_PLLSAI1P_DIV_27 + * @arg @ref LL_RCC_PLLSAI1P_DIV_28 + * @arg @ref LL_RCC_PLLSAI1P_DIV_29 + * @arg @ref LL_RCC_PLLSAI1P_DIV_30 + * @arg @ref LL_RCC_PLLSAI1P_DIV_31 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, Source); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M | RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV, + PLLM | (PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | PLLP); +} +#elif defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +/** + * @brief Configure PLLSAI1 used for SAI domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI1N/PLLSAI1PDIV can be written only when PLLSAI1 is disabled. + * @note This can be selected for SAI1 or SAI2 (*) + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLCFGR PLLM LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1PDIV LL_RCC_PLLSAI1_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_2 + * @arg @ref LL_RCC_PLLSAI1P_DIV_3 + * @arg @ref LL_RCC_PLLSAI1P_DIV_4 + * @arg @ref LL_RCC_PLLSAI1P_DIV_5 + * @arg @ref LL_RCC_PLLSAI1P_DIV_6 + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_8 + * @arg @ref LL_RCC_PLLSAI1P_DIV_9 + * @arg @ref LL_RCC_PLLSAI1P_DIV_10 + * @arg @ref LL_RCC_PLLSAI1P_DIV_11 + * @arg @ref LL_RCC_PLLSAI1P_DIV_12 + * @arg @ref LL_RCC_PLLSAI1P_DIV_13 + * @arg @ref LL_RCC_PLLSAI1P_DIV_14 + * @arg @ref LL_RCC_PLLSAI1P_DIV_15 + * @arg @ref LL_RCC_PLLSAI1P_DIV_16 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @arg @ref LL_RCC_PLLSAI1P_DIV_18 + * @arg @ref LL_RCC_PLLSAI1P_DIV_19 + * @arg @ref LL_RCC_PLLSAI1P_DIV_20 + * @arg @ref LL_RCC_PLLSAI1P_DIV_21 + * @arg @ref LL_RCC_PLLSAI1P_DIV_22 + * @arg @ref LL_RCC_PLLSAI1P_DIV_23 + * @arg @ref LL_RCC_PLLSAI1P_DIV_24 + * @arg @ref LL_RCC_PLLSAI1P_DIV_25 + * @arg @ref LL_RCC_PLLSAI1P_DIV_26 + * @arg @ref LL_RCC_PLLSAI1P_DIV_27 + * @arg @ref LL_RCC_PLLSAI1P_DIV_28 + * @arg @ref LL_RCC_PLLSAI1P_DIV_29 + * @arg @ref LL_RCC_PLLSAI1P_DIV_30 + * @arg @ref LL_RCC_PLLSAI1P_DIV_31 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV, + PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos | PLLP); +} +#else +/** + * @brief Configure PLLSAI1 used for SAI domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI1N/PLLSAI1P can be written only when PLLSAI1 is disabled. + * @note This can be selected for SAI1 or SAI2 (*) + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLCFGR PLLM LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_SAI\n + * PLLSAI1CFGR PLLSAI1P LL_RCC_PLLSAI1_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P, PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos | PLLP); +} +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT && RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +/** + * @brief Configure PLLSAI1 used for ADC domain clock + * @note PLL Source can be written only when PLL, PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI1M/PLLSAI1N/PLLSAI1R can be written only when PLLSAI1 is disabled. + * @note This can be selected for ADC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_ADC\n + * PLLSAI1CFGR PLLSAI1M LL_RCC_PLLSAI1_ConfigDomain_ADC\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_ADC\n + * PLLSAI1CFGR PLLSAI1R LL_RCC_PLLSAI1_ConfigDomain_ADC + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLR This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1R_DIV_2 + * @arg @ref LL_RCC_PLLSAI1R_DIV_4 + * @arg @ref LL_RCC_PLLSAI1R_DIV_6 + * @arg @ref LL_RCC_PLLSAI1R_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_ADC(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, Source); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M | RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R, + PLLM | (PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) | PLLR); +} +#else +/** + * @brief Configure PLLSAI1 used for ADC domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLN/PLLR can be written only when PLLSAI1 is disabled. + * @note This can be selected for ADC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI1_ConfigDomain_ADC\n + * PLLCFGR PLLM LL_RCC_PLLSAI1_ConfigDomain_ADC\n + * PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_ConfigDomain_ADC\n + * PLLSAI1CFGR PLLSAI1R LL_RCC_PLLSAI1_ConfigDomain_ADC + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLR This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1R_DIV_2 + * @arg @ref LL_RCC_PLLSAI1R_DIV_4 + * @arg @ref LL_RCC_PLLSAI1R_DIV_6 + * @arg @ref LL_RCC_PLLSAI1R_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_ConfigDomain_ADC(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R, PLLN << RCC_PLLSAI1CFGR_PLLSAI1N_Pos | PLLR); +} +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +/** + * @brief Get SAI1PLL multiplication factor for VCO + * @rmtoll PLLSAI1CFGR PLLSAI1N LL_RCC_PLLSAI1_GetN + * @retval Between 8 and 86 or 127 depending on devices + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_GetN(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos); +} + +#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT) +/** + * @brief Get SAI1PLL division factor for PLLSAI1P + * @note Used for PLLSAI1CLK (SAI1 or SAI2 (*) clock). + * @rmtoll PLLSAI1CFGR PLLSAI1PDIV LL_RCC_PLLSAI1_GetP + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_2 + * @arg @ref LL_RCC_PLLSAI1P_DIV_3 + * @arg @ref LL_RCC_PLLSAI1P_DIV_4 + * @arg @ref LL_RCC_PLLSAI1P_DIV_5 + * @arg @ref LL_RCC_PLLSAI1P_DIV_6 + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_8 + * @arg @ref LL_RCC_PLLSAI1P_DIV_9 + * @arg @ref LL_RCC_PLLSAI1P_DIV_10 + * @arg @ref LL_RCC_PLLSAI1P_DIV_11 + * @arg @ref LL_RCC_PLLSAI1P_DIV_12 + * @arg @ref LL_RCC_PLLSAI1P_DIV_13 + * @arg @ref LL_RCC_PLLSAI1P_DIV_14 + * @arg @ref LL_RCC_PLLSAI1P_DIV_15 + * @arg @ref LL_RCC_PLLSAI1P_DIV_16 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + * @arg @ref LL_RCC_PLLSAI1P_DIV_18 + * @arg @ref LL_RCC_PLLSAI1P_DIV_19 + * @arg @ref LL_RCC_PLLSAI1P_DIV_20 + * @arg @ref LL_RCC_PLLSAI1P_DIV_21 + * @arg @ref LL_RCC_PLLSAI1P_DIV_22 + * @arg @ref LL_RCC_PLLSAI1P_DIV_23 + * @arg @ref LL_RCC_PLLSAI1P_DIV_24 + * @arg @ref LL_RCC_PLLSAI1P_DIV_25 + * @arg @ref LL_RCC_PLLSAI1P_DIV_26 + * @arg @ref LL_RCC_PLLSAI1P_DIV_27 + * @arg @ref LL_RCC_PLLSAI1P_DIV_28 + * @arg @ref LL_RCC_PLLSAI1P_DIV_29 + * @arg @ref LL_RCC_PLLSAI1P_DIV_30 + * @arg @ref LL_RCC_PLLSAI1P_DIV_31 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_GetP(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV)); +} +#else +/** + * @brief Get SAI1PLL division factor for PLLSAI1P + * @note Used for PLLSAI1CLK (SAI1 or SAI2 (*) clock). + * @rmtoll PLLSAI1CFGR PLLSAI1P LL_RCC_PLLSAI1_GetP + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1P_DIV_7 + * @arg @ref LL_RCC_PLLSAI1P_DIV_17 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_GetP(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P)); +} +#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */ + +/** + * @brief Get SAI1PLL division factor for PLLSAI1Q + * @note Used PLL48M2CLK selected for USB, RNG, SDMMC (48 MHz clock) + * @rmtoll PLLSAI1CFGR PLLSAI1Q LL_RCC_PLLSAI1_GetQ + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI1Q_DIV_8 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_GetQ(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q)); +} + +/** + * @brief Get PLLSAI1 division factor for PLLSAIR + * @note Used for PLLADC1CLK (ADC clock) + * @rmtoll PLLSAI1CFGR PLLSAI1R LL_RCC_PLLSAI1_GetR + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1R_DIV_2 + * @arg @ref LL_RCC_PLLSAI1R_DIV_4 + * @arg @ref LL_RCC_PLLSAI1R_DIV_6 + * @arg @ref LL_RCC_PLLSAI1R_DIV_8 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_GetR(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R)); +} + +#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT) +/** + * @brief Get Division factor for the PLLSAI1 + * @rmtoll PLLSAI1CFGR PLLSAI1M LL_RCC_PLLSAI1_GetDivider + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI1M_DIV_1 + * @arg @ref LL_RCC_PLLSAI1M_DIV_2 + * @arg @ref LL_RCC_PLLSAI1M_DIV_3 + * @arg @ref LL_RCC_PLLSAI1M_DIV_4 + * @arg @ref LL_RCC_PLLSAI1M_DIV_5 + * @arg @ref LL_RCC_PLLSAI1M_DIV_6 + * @arg @ref LL_RCC_PLLSAI1M_DIV_7 + * @arg @ref LL_RCC_PLLSAI1M_DIV_8 + * @arg @ref LL_RCC_PLLSAI1M_DIV_9 + * @arg @ref LL_RCC_PLLSAI1M_DIV_10 + * @arg @ref LL_RCC_PLLSAI1M_DIV_11 + * @arg @ref LL_RCC_PLLSAI1M_DIV_12 + * @arg @ref LL_RCC_PLLSAI1M_DIV_13 + * @arg @ref LL_RCC_PLLSAI1M_DIV_14 + * @arg @ref LL_RCC_PLLSAI1M_DIV_15 + * @arg @ref LL_RCC_PLLSAI1M_DIV_16 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_GetDivider(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M)); +} +#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */ + +/** + * @brief Enable PLLSAI1 output mapped on SAI domain clock + * @rmtoll PLLSAI1CFGR PLLSAI1PEN LL_RCC_PLLSAI1_EnableDomain_SAI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_EnableDomain_SAI(void) +{ + SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PEN); +} + +/** + * @brief Disable PLLSAI1 output mapped on SAI domain clock + * @note In order to save power, when of the PLLSAI1 is + * not used, should be 0 + * @rmtoll PLLSAI1CFGR PLLSAI1PEN LL_RCC_PLLSAI1_DisableDomain_SAI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_DisableDomain_SAI(void) +{ + CLEAR_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PEN); +} + +/** + * @brief Check if PLLSAI1 output mapped on SAI domain clock is enabled + * @rmtoll PLLSAI1CFGR PLLSAI1PEN LL_RCC_PLLSAI1_IsEnabledDomain_SAI + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_IsEnabledDomain_SAI(void) +{ + return ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PEN) == (RCC_PLLSAI1CFGR_PLLSAI1PEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable PLLSAI1 output mapped on 48MHz domain clock + * @rmtoll PLLSAI1CFGR PLLSAI1QEN LL_RCC_PLLSAI1_EnableDomain_48M + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_EnableDomain_48M(void) +{ + SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN); +} + +/** + * @brief Disable PLLSAI1 output mapped on 48MHz domain clock + * @note In order to save power, when of the PLLSAI1 is + * not used, should be 0 + * @rmtoll PLLSAI1CFGR PLLSAI1QEN LL_RCC_PLLSAI1_DisableDomain_48M + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_DisableDomain_48M(void) +{ + CLEAR_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN); +} + +/** + * @brief Check if PLLSAI1 output mapped on SAI domain clock is enabled + * @rmtoll PLLSAI1CFGR PLLSAI1QEN LL_RCC_PLLSAI1_IsEnabledDomain_48M + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_IsEnabledDomain_48M(void) +{ + return ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN) == (RCC_PLLSAI1CFGR_PLLSAI1QEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable PLLSAI1 output mapped on ADC domain clock + * @rmtoll PLLSAI1CFGR PLLSAI1REN LL_RCC_PLLSAI1_EnableDomain_ADC + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_EnableDomain_ADC(void) +{ + SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1REN); +} + +/** + * @brief Disable PLLSAI1 output mapped on ADC domain clock + * @note In order to save power, when of the PLLSAI1 is + * not used, Main PLLSAI1 should be 0 + * @rmtoll PLLSAI1CFGR PLLSAI1REN LL_RCC_PLLSAI1_DisableDomain_ADC + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI1_DisableDomain_ADC(void) +{ + CLEAR_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1REN); +} + +/** + * @brief Check if PLLSAI1 output mapped on ADC domain clock is enabled + * @rmtoll PLLSAI1CFGR PLLSAI1REN LL_RCC_PLLSAI1_IsEnabledDomain_ADC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI1_IsEnabledDomain_ADC(void) +{ + return ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1REN) == (RCC_PLLSAI1CFGR_PLLSAI1REN)) ? 1UL : 0UL); +} + +/** + * @} + */ +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** @defgroup RCC_LL_EF_PLLSAI2 PLLSAI2 + * @{ + */ + +/** + * @brief Enable PLLSAI2 + * @rmtoll CR PLLSAI2ON LL_RCC_PLLSAI2_Enable + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_Enable(void) +{ + SET_BIT(RCC->CR, RCC_CR_PLLSAI2ON); +} + +/** + * @brief Disable PLLSAI2 + * @rmtoll CR PLLSAI2ON LL_RCC_PLLSAI2_Disable + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_Disable(void) +{ + CLEAR_BIT(RCC->CR, RCC_CR_PLLSAI2ON); +} + +/** + * @brief Check if PLLSAI2 Ready + * @rmtoll CR PLLSAI2RDY LL_RCC_PLLSAI2_IsReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_IsReady(void) +{ + return ((READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY) ? 1UL : 0UL); +} + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +/** + * @brief Configure PLLSAI2 used for SAI domain clock + * @note PLL Source can be written only when PLL, PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI2M/PLLSAI2N/PLLSAI2PDIV can be written only when PLLSAI2 is disabled. + * @note This can be selected for SAI1 or SAI2 + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2M LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2PDIV LL_RCC_PLLSAI2_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_2 + * @arg @ref LL_RCC_PLLSAI2P_DIV_3 + * @arg @ref LL_RCC_PLLSAI2P_DIV_4 + * @arg @ref LL_RCC_PLLSAI2P_DIV_5 + * @arg @ref LL_RCC_PLLSAI2P_DIV_6 + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_8 + * @arg @ref LL_RCC_PLLSAI2P_DIV_9 + * @arg @ref LL_RCC_PLLSAI2P_DIV_10 + * @arg @ref LL_RCC_PLLSAI2P_DIV_11 + * @arg @ref LL_RCC_PLLSAI2P_DIV_12 + * @arg @ref LL_RCC_PLLSAI2P_DIV_13 + * @arg @ref LL_RCC_PLLSAI2P_DIV_14 + * @arg @ref LL_RCC_PLLSAI2P_DIV_15 + * @arg @ref LL_RCC_PLLSAI2P_DIV_16 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @arg @ref LL_RCC_PLLSAI2P_DIV_18 + * @arg @ref LL_RCC_PLLSAI2P_DIV_19 + * @arg @ref LL_RCC_PLLSAI2P_DIV_20 + * @arg @ref LL_RCC_PLLSAI2P_DIV_21 + * @arg @ref LL_RCC_PLLSAI2P_DIV_22 + * @arg @ref LL_RCC_PLLSAI2P_DIV_23 + * @arg @ref LL_RCC_PLLSAI2P_DIV_24 + * @arg @ref LL_RCC_PLLSAI2P_DIV_25 + * @arg @ref LL_RCC_PLLSAI2P_DIV_26 + * @arg @ref LL_RCC_PLLSAI2P_DIV_27 + * @arg @ref LL_RCC_PLLSAI2P_DIV_28 + * @arg @ref LL_RCC_PLLSAI2P_DIV_29 + * @arg @ref LL_RCC_PLLSAI2P_DIV_30 + * @arg @ref LL_RCC_PLLSAI2P_DIV_31 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, Source); + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M | RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV, + PLLM | (PLLN << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | PLLP); +} +#elif defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +/** + * @brief Configure PLLSAI2 used for SAI domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI1 and PLLSAI2 are disabled. + * @note PLLSAI2N/PLLSAI2PDIV can be written only when PLLSAI2 is disabled. + * @note This can be selected for SAI1 or SAI2 + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLCFGR PLLM LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2PDIV LL_RCC_PLLSAI2_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 or 127 depending on devices + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_2 + * @arg @ref LL_RCC_PLLSAI2P_DIV_3 + * @arg @ref LL_RCC_PLLSAI2P_DIV_4 + * @arg @ref LL_RCC_PLLSAI2P_DIV_5 + * @arg @ref LL_RCC_PLLSAI2P_DIV_6 + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_8 + * @arg @ref LL_RCC_PLLSAI2P_DIV_9 + * @arg @ref LL_RCC_PLLSAI2P_DIV_10 + * @arg @ref LL_RCC_PLLSAI2P_DIV_11 + * @arg @ref LL_RCC_PLLSAI2P_DIV_12 + * @arg @ref LL_RCC_PLLSAI2P_DIV_13 + * @arg @ref LL_RCC_PLLSAI2P_DIV_14 + * @arg @ref LL_RCC_PLLSAI2P_DIV_15 + * @arg @ref LL_RCC_PLLSAI2P_DIV_16 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @arg @ref LL_RCC_PLLSAI2P_DIV_18 + * @arg @ref LL_RCC_PLLSAI2P_DIV_19 + * @arg @ref LL_RCC_PLLSAI2P_DIV_20 + * @arg @ref LL_RCC_PLLSAI2P_DIV_21 + * @arg @ref LL_RCC_PLLSAI2P_DIV_22 + * @arg @ref LL_RCC_PLLSAI2P_DIV_23 + * @arg @ref LL_RCC_PLLSAI2P_DIV_24 + * @arg @ref LL_RCC_PLLSAI2P_DIV_25 + * @arg @ref LL_RCC_PLLSAI2P_DIV_26 + * @arg @ref LL_RCC_PLLSAI2P_DIV_27 + * @arg @ref LL_RCC_PLLSAI2P_DIV_28 + * @arg @ref LL_RCC_PLLSAI2P_DIV_29 + * @arg @ref LL_RCC_PLLSAI2P_DIV_30 + * @arg @ref LL_RCC_PLLSAI2P_DIV_31 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV, PLLN << RCC_PLLSAI2CFGR_PLLSAI2N_Pos | PLLP); +} +#else +/** + * @brief Configure PLLSAI2 used for SAI domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI2 and PLLSAI2 are disabled. + * @note PLLSAI2N/PLLSAI2P can be written only when PLLSAI2 is disabled. + * @note This can be selected for SAI1 or SAI2 + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLCFGR PLLM LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_ConfigDomain_SAI\n + * PLLSAI2CFGR PLLSAI2P LL_RCC_PLLSAI2_ConfigDomain_SAI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 + * @param PLLP This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_ConfigDomain_SAI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P, PLLN << RCC_PLLSAI2CFGR_PLLSAI2N_Pos | PLLP); +} +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#if defined(DSI) +/** + * @brief Configure PLLSAI2 used for DSI domain clock + * @note PLL Source can be written only when PLL, PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI2M/PLLSAI2N/PLLSAI2Q can be written only when PLLSAI2 is disabled. + * @note This can be selected for DSI + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI2_ConfigDomain_DSI\n + * PLLSAI2CFGR PLLSAI2M LL_RCC_PLLSAI2_ConfigDomain_DSI\n + * PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_ConfigDomain_DSI\n + * PLLSAI2CFGR PLLSAI2Q LL_RCC_PLLSAI2_ConfigDomain_DSI + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + * @param PLLN Between 8 and 127 + * @param PLLQ This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_ConfigDomain_DSI(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLQ) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, Source); + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M | RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q, + (PLLN << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | PLLQ | PLLM); +} +#endif /* DSI */ + +#if defined(LTDC) +/** + * @brief Configure PLLSAI2 used for LTDC domain clock + * @note PLL Source can be written only when PLL, PLLSAI1 and PLLSAI2 (*) are disabled. + * @note PLLSAI2M/PLLSAI2N/PLLSAI2R can be written only when PLLSAI2 is disabled. + * @note This can be selected for LTDC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI2_ConfigDomain_LTDC\n + * PLLSAI2CFGR PLLSAI2M LL_RCC_PLLSAI2_ConfigDomain_LTDC\n + * PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_ConfigDomain_LTDC\n + * PLLSAI2CFGR PLLSAI2R LL_RCC_PLLSAI2_ConfigDomain_LTDC\n + * CCIPR2 PLLSAI2DIVR LL_RCC_PLLSAI2_ConfigDomain_LTDC + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + * @param PLLN Between 8 and 127 + * @param PLLR This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2R_DIV_2 + * @arg @ref LL_RCC_PLLSAI2R_DIV_4 + * @arg @ref LL_RCC_PLLSAI2R_DIV_6 + * @arg @ref LL_RCC_PLLSAI2R_DIV_8 + * @param PLLDIVR This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_2 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_4 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_8 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_16 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_ConfigDomain_LTDC(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR, uint32_t PLLDIVR) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, Source); + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M | RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R, + (PLLN << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) | PLLR | PLLM); + MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR, PLLDIVR); +} +#else +/** + * @brief Configure PLLSAI2 used for ADC domain clock + * @note PLL Source and PLLM Divider can be written only when PLL, + * PLLSAI2 and PLLSAI2 are disabled. + * @note PLLSAI2N/PLLSAI2R can be written only when PLLSAI2 is disabled. + * @note This can be selected for ADC + * @rmtoll PLLCFGR PLLSRC LL_RCC_PLLSAI2_ConfigDomain_ADC\n + * PLLCFGR PLLM LL_RCC_PLLSAI2_ConfigDomain_ADC\n + * PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_ConfigDomain_ADC\n + * PLLSAI2CFGR PLLSAI2R LL_RCC_PLLSAI2_ConfigDomain_ADC + * @param Source This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSOURCE_NONE + * @arg @ref LL_RCC_PLLSOURCE_MSI + * @arg @ref LL_RCC_PLLSOURCE_HSI + * @arg @ref LL_RCC_PLLSOURCE_HSE + * @param PLLM This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLM_DIV_1 + * @arg @ref LL_RCC_PLLM_DIV_2 + * @arg @ref LL_RCC_PLLM_DIV_3 + * @arg @ref LL_RCC_PLLM_DIV_4 + * @arg @ref LL_RCC_PLLM_DIV_5 + * @arg @ref LL_RCC_PLLM_DIV_6 + * @arg @ref LL_RCC_PLLM_DIV_7 + * @arg @ref LL_RCC_PLLM_DIV_8 + * @param PLLN Between 8 and 86 + * @param PLLR This parameter can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2R_DIV_2 + * @arg @ref LL_RCC_PLLSAI2R_DIV_4 + * @arg @ref LL_RCC_PLLSAI2R_DIV_6 + * @arg @ref LL_RCC_PLLSAI2R_DIV_8 + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_ConfigDomain_ADC(uint32_t Source, uint32_t PLLM, uint32_t PLLN, uint32_t PLLR) +{ + MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, Source | PLLM); + MODIFY_REG(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R, PLLN << RCC_PLLSAI2CFGR_PLLSAI2N_Pos | PLLR); +} +#endif /* LTDC */ + +/** + * @brief Get SAI2PLL multiplication factor for VCO + * @rmtoll PLLSAI2CFGR PLLSAI2N LL_RCC_PLLSAI2_GetN + * @retval Between 8 and 86 or 127 depending on devices + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetN(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos); +} + +#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT) +/** + * @brief Get SAI2PLL division factor for PLLSAI2P + * @note Used for PLLSAI2CLK (SAI1 or SAI2 clock). + * @rmtoll PLLSAI2CFGR PLLSAI2PDIV LL_RCC_PLLSAI2_GetP + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_2 + * @arg @ref LL_RCC_PLLSAI2P_DIV_3 + * @arg @ref LL_RCC_PLLSAI2P_DIV_4 + * @arg @ref LL_RCC_PLLSAI2P_DIV_5 + * @arg @ref LL_RCC_PLLSAI2P_DIV_6 + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_8 + * @arg @ref LL_RCC_PLLSAI2P_DIV_9 + * @arg @ref LL_RCC_PLLSAI2P_DIV_10 + * @arg @ref LL_RCC_PLLSAI2P_DIV_11 + * @arg @ref LL_RCC_PLLSAI2P_DIV_12 + * @arg @ref LL_RCC_PLLSAI2P_DIV_13 + * @arg @ref LL_RCC_PLLSAI2P_DIV_14 + * @arg @ref LL_RCC_PLLSAI2P_DIV_15 + * @arg @ref LL_RCC_PLLSAI2P_DIV_16 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + * @arg @ref LL_RCC_PLLSAI2P_DIV_18 + * @arg @ref LL_RCC_PLLSAI2P_DIV_19 + * @arg @ref LL_RCC_PLLSAI2P_DIV_20 + * @arg @ref LL_RCC_PLLSAI2P_DIV_21 + * @arg @ref LL_RCC_PLLSAI2P_DIV_22 + * @arg @ref LL_RCC_PLLSAI2P_DIV_23 + * @arg @ref LL_RCC_PLLSAI2P_DIV_24 + * @arg @ref LL_RCC_PLLSAI2P_DIV_25 + * @arg @ref LL_RCC_PLLSAI2P_DIV_26 + * @arg @ref LL_RCC_PLLSAI2P_DIV_27 + * @arg @ref LL_RCC_PLLSAI2P_DIV_28 + * @arg @ref LL_RCC_PLLSAI2P_DIV_29 + * @arg @ref LL_RCC_PLLSAI2P_DIV_30 + * @arg @ref LL_RCC_PLLSAI2P_DIV_31 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetP(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PDIV)); +} +#else +/** + * @brief Get SAI2PLL division factor for PLLSAI2P + * @note Used for PLLSAI2CLK (SAI1 or SAI2 clock). + * @rmtoll PLLSAI2CFGR PLLSAI2P LL_RCC_PLLSAI2_GetP + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2P_DIV_7 + * @arg @ref LL_RCC_PLLSAI2P_DIV_17 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetP(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P)); +} +#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */ + +#if defined(RCC_PLLSAI2Q_DIV_SUPPORT) +/** + * @brief Get division factor for PLLSAI2Q + * @note Used for PLLDSICLK (DSI clock) + * @rmtoll PLLSAI2CFGR PLLSAI2Q LL_RCC_PLLSAI2_GetQ + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2Q_DIV_2 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_4 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_6 + * @arg @ref LL_RCC_PLLSAI2Q_DIV_8 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetQ(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q)); +} +#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */ + +/** + * @brief Get SAI2PLL division factor for PLLSAI2R + * @note Used for PLLADC2CLK (ADC clock) or PLLLCDCLK (LTDC clock) depending on devices + * @rmtoll PLLSAI2CFGR PLLSAI2R LL_RCC_PLLSAI2_GetR + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2R_DIV_2 + * @arg @ref LL_RCC_PLLSAI2R_DIV_4 + * @arg @ref LL_RCC_PLLSAI2R_DIV_6 + * @arg @ref LL_RCC_PLLSAI2R_DIV_8 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetR(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R)); +} + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) +/** + * @brief Get Division factor for the PLLSAI2 + * @rmtoll PLLSAI2CFGR PLLSAI2M LL_RCC_PLLSAI2_GetDivider + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2M_DIV_1 + * @arg @ref LL_RCC_PLLSAI2M_DIV_2 + * @arg @ref LL_RCC_PLLSAI2M_DIV_3 + * @arg @ref LL_RCC_PLLSAI2M_DIV_4 + * @arg @ref LL_RCC_PLLSAI2M_DIV_5 + * @arg @ref LL_RCC_PLLSAI2M_DIV_6 + * @arg @ref LL_RCC_PLLSAI2M_DIV_7 + * @arg @ref LL_RCC_PLLSAI2M_DIV_8 + * @arg @ref LL_RCC_PLLSAI2M_DIV_9 + * @arg @ref LL_RCC_PLLSAI2M_DIV_10 + * @arg @ref LL_RCC_PLLSAI2M_DIV_11 + * @arg @ref LL_RCC_PLLSAI2M_DIV_12 + * @arg @ref LL_RCC_PLLSAI2M_DIV_13 + * @arg @ref LL_RCC_PLLSAI2M_DIV_14 + * @arg @ref LL_RCC_PLLSAI2M_DIV_15 + * @arg @ref LL_RCC_PLLSAI2M_DIV_16 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetDivider(void) +{ + return (uint32_t)(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M)); +} +#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */ + +#if defined(RCC_CCIPR2_PLLSAI2DIVR) +/** + * @brief Get PLLSAI2 division factor for PLLSAI2DIVR + * @note Used for LTDC domain clock + * @rmtoll CCIPR2 PLLSAI2DIVR LL_RCC_PLLSAI2_GetDIVR + * @retval Returned value can be one of the following values: + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_2 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_4 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_8 + * @arg @ref LL_RCC_PLLSAI2DIVR_DIV_16 + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_GetDIVR(void) +{ + return (uint32_t)(READ_BIT(RCC->CCIPR2, RCC_CCIPR2_PLLSAI2DIVR)); +} +#endif /* RCC_CCIPR2_PLLSAI2DIVR */ + +/** + * @brief Enable PLLSAI2 output mapped on SAI domain clock + * @rmtoll PLLSAI2CFGR PLLSAI2PEN LL_RCC_PLLSAI2_EnableDomain_SAI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_EnableDomain_SAI(void) +{ + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PEN); +} + +/** + * @brief Disable PLLSAI2 output mapped on SAI domain clock + * @note In order to save power, when of the PLLSAI2 is + * not used, should be 0 + * @rmtoll PLLSAI2CFGR PLLSAI2PEN LL_RCC_PLLSAI2_DisableDomain_SAI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_DisableDomain_SAI(void) +{ + CLEAR_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PEN); +} + +/** + * @brief Check if PLLSAI2 output mapped on SAI domain clock is enabled + * @rmtoll PLLSAI2CFGR PLLSAI2PEN LL_RCC_PLLSAI2_IsEnabledDomain_SAI + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_IsEnabledDomain_SAI(void) +{ + return ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PEN) == (RCC_PLLSAI2CFGR_PLLSAI2PEN)) ? 1UL : 0UL); +} + +#if defined(DSI) +/** + * @brief Enable PLLSAI2 output mapped on DSI domain clock + * @rmtoll PLLSAI2CFGR PLLSAI2QEN LL_RCC_PLLSAI2_EnableDomain_DSI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_EnableDomain_DSI(void) +{ + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2QEN); +} + +/** + * @brief Disable PLLSAI2 output mapped on DSI domain clock + * @note In order to save power, when of the PLLSAI2 is + * not used, Main PLLSAI2 should be 0 + * @rmtoll PLLSAI2CFGR PLLSAI2QEN LL_RCC_PLLSAI2_DisableDomain_DSI + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_DisableDomain_DSI(void) +{ + CLEAR_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2QEN); +} + +/** + * @brief Check if PLLSAI2 output mapped on DSI domain clock is enabled + * @rmtoll PLLSAI2CFGR PLLSAI2QEN LL_RCC_PLLSAI2_IsEnabledDomain_DSI + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_IsEnabledDomain_DSI(void) +{ + return ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2QEN) == (RCC_PLLSAI2CFGR_PLLSAI2QEN)) ? 1UL : 0UL); +} +#endif /* DSI */ + +#if defined(LTDC) +/** + * @brief Enable PLLSAI2 output mapped on LTDC domain clock + * @rmtoll PLLSAI2CFGR PLLSAI2REN LL_RCC_PLLSAI2_EnableDomain_LTDC + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_EnableDomain_LTDC(void) +{ + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2REN); +} + +/** + * @brief Disable PLLSAI2 output mapped on LTDC domain clock + * @note In order to save power, when of the PLLSAI2 is + * not used, Main PLLSAI2 should be 0 + * @rmtoll PLLSAI2CFGR PLLSAI2REN LL_RCC_PLLSAI2_DisableDomain_LTDC + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_DisableDomain_LTDC(void) +{ + CLEAR_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2REN); +} + +/** + * @brief Check if PLLSAI2 output mapped on LTDC domain clock is enabled + * @rmtoll PLLSAI2CFGR PLLSAI2REN LL_RCC_PLLSAI2_IsEnabledDomain_LTDC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_IsEnabledDomain_LTDC(void) +{ + return ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2REN) == (RCC_PLLSAI2CFGR_PLLSAI2REN)) ? 1UL : 0UL); +} +#else +/** + * @brief Enable PLLSAI2 output mapped on ADC domain clock + * @rmtoll PLLSAI2CFGR PLLSAI2REN LL_RCC_PLLSAI2_EnableDomain_ADC + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_EnableDomain_ADC(void) +{ + SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2REN); +} + +/** + * @brief Disable PLLSAI2 output mapped on ADC domain clock + * @note In order to save power, when of the PLLSAI2 is + * not used, Main PLLSAI2 should be 0 + * @rmtoll PLLSAI2CFGR PLLSAI2REN LL_RCC_PLLSAI2_DisableDomain_ADC + * @retval None + */ +__STATIC_INLINE void LL_RCC_PLLSAI2_DisableDomain_ADC(void) +{ + CLEAR_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2REN); +} + +/** + * @brief Check if PLLSAI2 output mapped on ADC domain clock is enabled + * @rmtoll PLLSAI2CFGR PLLSAI2REN LL_RCC_PLLSAI2_IsEnabledDomain_ADC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_PLLSAI2_IsEnabledDomain_ADC(void) +{ + return ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2REN) == (RCC_PLLSAI2CFGR_PLLSAI2REN)) ? 1UL : 0UL); +} +#endif /* LTDC */ + +/** + * @} + */ +#endif /* RCC_PLLSAI2_SUPPORT */ + +#if defined(OCTOSPI1) +/** @defgroup RCC_LL_EF_OCTOSPI OCTOSPI + * @{ + */ + +/** + * @brief Configure OCTOSPI1 DQS delay + * @rmtoll DLYCFGR OCTOSPI1_DLY LL_RCC_OCTOSPI1_DelayConfig + * @param Delay OCTOSPI1 DQS delay between 0 and 15 + * @retval None + */ +__STATIC_INLINE void LL_RCC_OCTOSPI1_DelayConfig(uint32_t Delay) +{ + MODIFY_REG(RCC->DLYCFGR, RCC_DLYCFGR_OCTOSPI1_DLY, Delay); +} + +#if defined(OCTOSPI2) +/** + * @brief Configure OCTOSPI2 DQS delay + * @rmtoll DLYCFGR OCTOSPI2_DLY LL_RCC_OCTOSPI2_DelayConfig + * @param Delay OCTOSPI2 DQS delay between 0 and 15 + * @retval None + */ +__STATIC_INLINE void LL_RCC_OCTOSPI2_DelayConfig(uint32_t Delay) +{ + MODIFY_REG(RCC->DLYCFGR, RCC_DLYCFGR_OCTOSPI2_DLY, (Delay << RCC_DLYCFGR_OCTOSPI2_DLY_Pos)); +} +#endif /* OCTOSPI2 */ + +/** + * @} + */ +#endif /* OCTOSPI1 */ + +/** @defgroup RCC_LL_EF_FLAG_Management FLAG Management + * @{ + */ + +/** + * @brief Clear LSI ready interrupt flag + * @rmtoll CICR LSIRDYC LL_RCC_ClearFlag_LSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_LSIRDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_LSIRDYC); +} + +/** + * @brief Clear LSE ready interrupt flag + * @rmtoll CICR LSERDYC LL_RCC_ClearFlag_LSERDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_LSERDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_LSERDYC); +} + +/** + * @brief Clear MSI ready interrupt flag + * @rmtoll CICR MSIRDYC LL_RCC_ClearFlag_MSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_MSIRDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_MSIRDYC); +} + +/** + * @brief Clear HSI ready interrupt flag + * @rmtoll CICR HSIRDYC LL_RCC_ClearFlag_HSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_HSIRDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_HSIRDYC); +} + +/** + * @brief Clear HSE ready interrupt flag + * @rmtoll CICR HSERDYC LL_RCC_ClearFlag_HSERDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_HSERDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_HSERDYC); +} + +/** + * @brief Clear PLL ready interrupt flag + * @rmtoll CICR PLLRDYC LL_RCC_ClearFlag_PLLRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_PLLRDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_PLLRDYC); +} + +#if defined(RCC_HSI48_SUPPORT) +/** + * @brief Clear HSI48 ready interrupt flag + * @rmtoll CICR HSI48RDYC LL_RCC_ClearFlag_HSI48RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_HSI48RDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_HSI48RDYC); +} +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** + * @brief Clear PLLSAI1 ready interrupt flag + * @rmtoll CICR PLLSAI1RDYC LL_RCC_ClearFlag_PLLSAI1RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_PLLSAI1RDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_PLLSAI1RDYC); +} +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Clear PLLSAI1 ready interrupt flag + * @rmtoll CICR PLLSAI2RDYC LL_RCC_ClearFlag_PLLSAI2RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_PLLSAI2RDY(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_PLLSAI2RDYC); +} +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Clear Clock security system interrupt flag + * @rmtoll CICR CSSC LL_RCC_ClearFlag_HSECSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_HSECSS(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_CSSC); +} + +/** + * @brief Clear LSE Clock security system interrupt flag + * @rmtoll CICR LSECSSC LL_RCC_ClearFlag_LSECSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearFlag_LSECSS(void) +{ + SET_BIT(RCC->CICR, RCC_CICR_LSECSSC); +} + +/** + * @brief Check if LSI ready interrupt occurred or not + * @rmtoll CIFR LSIRDYF LL_RCC_IsActiveFlag_LSIRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_LSIRDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_LSIRDYF) == RCC_CIFR_LSIRDYF) ? 1UL : 0UL); +} + +/** + * @brief Check if LSE ready interrupt occurred or not + * @rmtoll CIFR LSERDYF LL_RCC_IsActiveFlag_LSERDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_LSERDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_LSERDYF) == RCC_CIFR_LSERDYF) ? 1UL : 0UL); +} + +/** + * @brief Check if MSI ready interrupt occurred or not + * @rmtoll CIFR MSIRDYF LL_RCC_IsActiveFlag_MSIRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_MSIRDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_MSIRDYF) == RCC_CIFR_MSIRDYF) ? 1UL : 0UL); +} + +/** + * @brief Check if HSI ready interrupt occurred or not + * @rmtoll CIFR HSIRDYF LL_RCC_IsActiveFlag_HSIRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_HSIRDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_HSIRDYF) == RCC_CIFR_HSIRDYF) ? 1UL : 0UL); +} + +/** + * @brief Check if HSE ready interrupt occurred or not + * @rmtoll CIFR HSERDYF LL_RCC_IsActiveFlag_HSERDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_HSERDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_HSERDYF) == RCC_CIFR_HSERDYF) ? 1UL : 0UL); +} + +/** + * @brief Check if PLL ready interrupt occurred or not + * @rmtoll CIFR PLLRDYF LL_RCC_IsActiveFlag_PLLRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_PLLRDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_PLLRDYF) == RCC_CIFR_PLLRDYF) ? 1UL : 0UL); +} + +#if defined(RCC_HSI48_SUPPORT) +/** + * @brief Check if HSI48 ready interrupt occurred or not + * @rmtoll CIR HSI48RDYF LL_RCC_IsActiveFlag_HSI48RDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_HSI48RDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_HSI48RDYF) == RCC_CIFR_HSI48RDYF) ? 1UL : 0UL); +} +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** + * @brief Check if PLLSAI1 ready interrupt occurred or not + * @rmtoll CIFR PLLSAI1RDYF LL_RCC_IsActiveFlag_PLLSAI1RDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_PLLSAI1RDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_PLLSAI1RDYF) == RCC_CIFR_PLLSAI1RDYF) ? 1UL : 0UL); +} +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Check if PLLSAI1 ready interrupt occurred or not + * @rmtoll CIFR PLLSAI2RDYF LL_RCC_IsActiveFlag_PLLSAI2RDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_PLLSAI2RDY(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_PLLSAI2RDYF) == RCC_CIFR_PLLSAI2RDYF) ? 1UL : 0UL); +} +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Check if Clock security system interrupt occurred or not + * @rmtoll CIFR CSSF LL_RCC_IsActiveFlag_HSECSS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_HSECSS(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_CSSF) == RCC_CIFR_CSSF) ? 1UL : 0UL); +} + +/** + * @brief Check if LSE Clock security system interrupt occurred or not + * @rmtoll CIFR LSECSSF LL_RCC_IsActiveFlag_LSECSS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_LSECSS(void) +{ + return ((READ_BIT(RCC->CIFR, RCC_CIFR_LSECSSF) == RCC_CIFR_LSECSSF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag FW reset is set or not. + * @rmtoll CSR FWRSTF LL_RCC_IsActiveFlag_FWRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_FWRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_FWRSTF) == RCC_CSR_FWRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag Independent Watchdog reset is set or not. + * @rmtoll CSR IWDGRSTF LL_RCC_IsActiveFlag_IWDGRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_IWDGRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_IWDGRSTF) == RCC_CSR_IWDGRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag Low Power reset is set or not. + * @rmtoll CSR LPWRRSTF LL_RCC_IsActiveFlag_LPWRRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_LPWRRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_LPWRRSTF) == RCC_CSR_LPWRRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag is set or not. + * @rmtoll CSR OBLRSTF LL_RCC_IsActiveFlag_OBLRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_OBLRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_OBLRSTF) == RCC_CSR_OBLRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag Pin reset is set or not. + * @rmtoll CSR PINRSTF LL_RCC_IsActiveFlag_PINRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_PINRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_PINRSTF) == RCC_CSR_PINRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag Software reset is set or not. + * @rmtoll CSR SFTRSTF LL_RCC_IsActiveFlag_SFTRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_SFTRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_SFTRSTF) == RCC_CSR_SFTRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag Window Watchdog reset is set or not. + * @rmtoll CSR WWDGRSTF LL_RCC_IsActiveFlag_WWDGRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_WWDGRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_WWDGRSTF) == RCC_CSR_WWDGRSTF) ? 1UL : 0UL); +} + +/** + * @brief Check if RCC flag BOR reset is set or not. + * @rmtoll CSR BORRSTF LL_RCC_IsActiveFlag_BORRST + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsActiveFlag_BORRST(void) +{ + return ((READ_BIT(RCC->CSR, RCC_CSR_BORRSTF) == RCC_CSR_BORRSTF) ? 1UL : 0UL); +} + +/** + * @brief Set RMVF bit to clear the reset flags. + * @rmtoll CSR RMVF LL_RCC_ClearResetFlags + * @retval None + */ +__STATIC_INLINE void LL_RCC_ClearResetFlags(void) +{ + SET_BIT(RCC->CSR, RCC_CSR_RMVF); +} + +/** + * @} + */ + +/** @defgroup RCC_LL_EF_IT_Management IT Management + * @{ + */ + +/** + * @brief Enable LSI ready interrupt + * @rmtoll CIER LSIRDYIE LL_RCC_EnableIT_LSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_LSIRDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_LSIRDYIE); +} + +/** + * @brief Enable LSE ready interrupt + * @rmtoll CIER LSERDYIE LL_RCC_EnableIT_LSERDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_LSERDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_LSERDYIE); +} + +/** + * @brief Enable MSI ready interrupt + * @rmtoll CIER MSIRDYIE LL_RCC_EnableIT_MSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_MSIRDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_MSIRDYIE); +} + +/** + * @brief Enable HSI ready interrupt + * @rmtoll CIER HSIRDYIE LL_RCC_EnableIT_HSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_HSIRDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_HSIRDYIE); +} + +/** + * @brief Enable HSE ready interrupt + * @rmtoll CIER HSERDYIE LL_RCC_EnableIT_HSERDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_HSERDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_HSERDYIE); +} + +/** + * @brief Enable PLL ready interrupt + * @rmtoll CIER PLLRDYIE LL_RCC_EnableIT_PLLRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_PLLRDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_PLLRDYIE); +} + +#if defined(RCC_HSI48_SUPPORT) +/** + * @brief Enable HSI48 ready interrupt + * @rmtoll CIER HSI48RDYIE LL_RCC_EnableIT_HSI48RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_HSI48RDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_HSI48RDYIE); +} +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** + * @brief Enable PLLSAI1 ready interrupt + * @rmtoll CIER PLLSAI1RDYIE LL_RCC_EnableIT_PLLSAI1RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_PLLSAI1RDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE); +} +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Enable PLLSAI2 ready interrupt + * @rmtoll CIER PLLSAI2RDYIE LL_RCC_EnableIT_PLLSAI2RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_PLLSAI2RDY(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE); +} +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Enable LSE clock security system interrupt + * @rmtoll CIER LSECSSIE LL_RCC_EnableIT_LSECSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_EnableIT_LSECSS(void) +{ + SET_BIT(RCC->CIER, RCC_CIER_LSECSSIE); +} + +/** + * @brief Disable LSI ready interrupt + * @rmtoll CIER LSIRDYIE LL_RCC_DisableIT_LSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_LSIRDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_LSIRDYIE); +} + +/** + * @brief Disable LSE ready interrupt + * @rmtoll CIER LSERDYIE LL_RCC_DisableIT_LSERDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_LSERDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_LSERDYIE); +} + +/** + * @brief Disable MSI ready interrupt + * @rmtoll CIER MSIRDYIE LL_RCC_DisableIT_MSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_MSIRDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_MSIRDYIE); +} + +/** + * @brief Disable HSI ready interrupt + * @rmtoll CIER HSIRDYIE LL_RCC_DisableIT_HSIRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_HSIRDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_HSIRDYIE); +} + +/** + * @brief Disable HSE ready interrupt + * @rmtoll CIER HSERDYIE LL_RCC_DisableIT_HSERDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_HSERDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_HSERDYIE); +} + +/** + * @brief Disable PLL ready interrupt + * @rmtoll CIER PLLRDYIE LL_RCC_DisableIT_PLLRDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_PLLRDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_PLLRDYIE); +} + +#if defined(RCC_HSI48_SUPPORT) +/** + * @brief Disable HSI48 ready interrupt + * @rmtoll CIER HSI48RDYIE LL_RCC_DisableIT_HSI48RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_HSI48RDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_HSI48RDYIE); +} +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** + * @brief Disable PLLSAI1 ready interrupt + * @rmtoll CIER PLLSAI1RDYIE LL_RCC_DisableIT_PLLSAI1RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_PLLSAI1RDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE); +} +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Disable PLLSAI2 ready interrupt + * @rmtoll CIER PLLSAI2RDYIE LL_RCC_DisableIT_PLLSAI2RDY + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_PLLSAI2RDY(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE); +} +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Disable LSE clock security system interrupt + * @rmtoll CIER LSECSSIE LL_RCC_DisableIT_LSECSS + * @retval None + */ +__STATIC_INLINE void LL_RCC_DisableIT_LSECSS(void) +{ + CLEAR_BIT(RCC->CIER, RCC_CIER_LSECSSIE); +} + +/** + * @brief Checks if LSI ready interrupt source is enabled or disabled. + * @rmtoll CIER LSIRDYIE LL_RCC_IsEnabledIT_LSIRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_LSIRDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_LSIRDYIE) == RCC_CIER_LSIRDYIE) ? 1UL : 0UL); +} + +/** + * @brief Checks if LSE ready interrupt source is enabled or disabled. + * @rmtoll CIER LSERDYIE LL_RCC_IsEnabledIT_LSERDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_LSERDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_LSERDYIE) == RCC_CIER_LSERDYIE) ? 1UL : 0UL); +} + +/** + * @brief Checks if MSI ready interrupt source is enabled or disabled. + * @rmtoll CIER MSIRDYIE LL_RCC_IsEnabledIT_MSIRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_MSIRDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_MSIRDYIE) == RCC_CIER_MSIRDYIE) ? 1UL : 0UL); +} + +/** + * @brief Checks if HSI ready interrupt source is enabled or disabled. + * @rmtoll CIER HSIRDYIE LL_RCC_IsEnabledIT_HSIRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_HSIRDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_HSIRDYIE) == RCC_CIER_HSIRDYIE) ? 1UL : 0UL); +} + +/** + * @brief Checks if HSE ready interrupt source is enabled or disabled. + * @rmtoll CIER HSERDYIE LL_RCC_IsEnabledIT_HSERDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_HSERDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_HSERDYIE) == RCC_CIER_HSERDYIE) ? 1UL : 0UL); +} + +/** + * @brief Checks if PLL ready interrupt source is enabled or disabled. + * @rmtoll CIER PLLRDYIE LL_RCC_IsEnabledIT_PLLRDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_PLLRDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_PLLRDYIE) == RCC_CIER_PLLRDYIE) ? 1UL : 0UL); +} + +#if defined(RCC_HSI48_SUPPORT) +/** + * @brief Checks if HSI48 ready interrupt source is enabled or disabled. + * @rmtoll CIER HSI48RDYIE LL_RCC_IsEnabledIT_HSI48RDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_HSI48RDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_HSI48RDYIE) == RCC_CIER_HSI48RDYIE) ? 1UL : 0UL); +} +#endif /* RCC_HSI48_SUPPORT */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** + * @brief Checks if PLLSAI1 ready interrupt source is enabled or disabled. + * @rmtoll CIER PLLSAI1RDYIE LL_RCC_IsEnabledIT_PLLSAI1RDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_PLLSAI1RDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_PLLSAI1RDYIE) == RCC_CIER_PLLSAI1RDYIE) ? 1UL : 0UL); +} +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Checks if PLLSAI2 ready interrupt source is enabled or disabled. + * @rmtoll CIER PLLSAI2RDYIE LL_RCC_IsEnabledIT_PLLSAI2RDY + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_PLLSAI2RDY(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_PLLSAI2RDYIE) == RCC_CIER_PLLSAI2RDYIE) ? 1UL : 0UL); +} +#endif /* RCC_PLLSAI2_SUPPORT */ + +/** + * @brief Checks if LSECSS interrupt source is enabled or disabled. + * @rmtoll CIER LSECSSIE LL_RCC_IsEnabledIT_LSECSS + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RCC_IsEnabledIT_LSECSS(void) +{ + return ((READ_BIT(RCC->CIER, RCC_CIER_LSECSSIE) == RCC_CIER_LSECSSIE) ? 1UL : 0UL); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RCC_LL_EF_Init De-initialization function + * @{ + */ +ErrorStatus LL_RCC_DeInit(void); +/** + * @} + */ + +/** @defgroup RCC_LL_EF_Get_Freq Get system and peripherals clocks frequency functions + * @{ + */ +void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks); +uint32_t LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource); +#if defined(UART4) || defined(UART5) +uint32_t LL_RCC_GetUARTClockFreq(uint32_t UARTxSource); +#endif /* UART4 || UART5 */ +uint32_t LL_RCC_GetI2CClockFreq(uint32_t I2CxSource); +uint32_t LL_RCC_GetLPUARTClockFreq(uint32_t LPUARTxSource); +uint32_t LL_RCC_GetLPTIMClockFreq(uint32_t LPTIMxSource); +#if defined(SAI1) +uint32_t LL_RCC_GetSAIClockFreq(uint32_t SAIxSource); +#endif /* SAI1 */ +#if defined(SDMMC1) +#if defined(RCC_CCIPR2_SDMMCSEL) +uint32_t LL_RCC_GetSDMMCKernelClockFreq(uint32_t SDMMCxSource); +#endif +uint32_t LL_RCC_GetSDMMCClockFreq(uint32_t SDMMCxSource); +#endif /* SDMMC1 */ +uint32_t LL_RCC_GetRNGClockFreq(uint32_t RNGxSource); +#if defined(USB_OTG_FS) || defined(USB) +uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource); +#endif /* USB_OTG_FS || USB */ +uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource); +#if defined(SWPMI1) +uint32_t LL_RCC_GetSWPMIClockFreq(uint32_t SWPMIxSource); +#endif /* SWPMI1 */ +#if defined(DFSDM1_Channel0) +uint32_t LL_RCC_GetDFSDMClockFreq(uint32_t DFSDMxSource); +#if defined(RCC_CCIPR2_DFSDM1SEL) +uint32_t LL_RCC_GetDFSDMAudioClockFreq(uint32_t DFSDMxSource); +#endif /* RCC_CCIPR2_DFSDM1SEL */ +#endif /* DFSDM1_Channel0 */ +#if defined(LTDC) +uint32_t LL_RCC_GetLTDCClockFreq(uint32_t LTDCxSource); +#endif /* LTDC */ +#if defined(DSI) +uint32_t LL_RCC_GetDSIClockFreq(uint32_t DSIxSource); +#endif /* DSI */ +#if defined(OCTOSPI1) +uint32_t LL_RCC_GetOCTOSPIClockFreq(uint32_t OCTOSPIxSource); +#endif /* OCTOSPI1 */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(RCC) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_RCC_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h new file mode 100644 index 0000000..d377cca --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_spi.h @@ -0,0 +1,1418 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_spi.h + * @author MCD Application Team + * @brief Header file of SPI 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 STM32L4xx_LL_SPI_H +#define STM32L4xx_LL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @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_4BIT (SPI_CR2_DS_0 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 4 bits */ +#define LL_SPI_DATAWIDTH_5BIT (SPI_CR2_DS_2) /*!< Data length for SPI transfer: 5 bits */ +#define LL_SPI_DATAWIDTH_6BIT (SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 6 bits */ +#define LL_SPI_DATAWIDTH_7BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 7 bits */ +#define LL_SPI_DATAWIDTH_8BIT (SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 8 bits */ +#define LL_SPI_DATAWIDTH_9BIT (SPI_CR2_DS_3) /*!< Data length for SPI transfer: 9 bits */ +#define LL_SPI_DATAWIDTH_10BIT (SPI_CR2_DS_3 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 10 bits */ +#define LL_SPI_DATAWIDTH_11BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 11 bits */ +#define LL_SPI_DATAWIDTH_12BIT (SPI_CR2_DS_3 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 12 bits */ +#define LL_SPI_DATAWIDTH_13BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2) /*!< Data length for SPI transfer: 13 bits */ +#define LL_SPI_DATAWIDTH_14BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_0) /*!< Data length for SPI transfer: 14 bits */ +#define LL_SPI_DATAWIDTH_15BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1) /*!< Data length for SPI transfer: 15 bits */ +#define LL_SPI_DATAWIDTH_16BIT (SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0) /*!< 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 */ + +/** @defgroup SPI_LL_EC_CRC_LENGTH CRC Length + * @{ + */ +#define LL_SPI_CRC_8BIT 0x00000000U /*!< 8-bit CRC length */ +#define LL_SPI_CRC_16BIT (SPI_CR1_CRCL) /*!< 16-bit CRC length */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_RX_FIFO_TH RX FIFO Threshold + * @{ + */ +#define LL_SPI_RX_FIFO_TH_HALF 0x00000000U /*!< RXNE event is generated if FIFO level is greater than or equal to 1/2 (16-bit) */ +#define LL_SPI_RX_FIFO_TH_QUARTER (SPI_CR2_FRXTH) /*!< RXNE event is generated if FIFO level is greater than or equal to 1/4 (8-bit) */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_RX_FIFO RX FIFO Level + * @{ + */ +#define LL_SPI_RX_FIFO_EMPTY 0x00000000U /*!< FIFO reception empty */ +#define LL_SPI_RX_FIFO_QUARTER_FULL (SPI_SR_FRLVL_0) /*!< FIFO reception 1/4 */ +#define LL_SPI_RX_FIFO_HALF_FULL (SPI_SR_FRLVL_1) /*!< FIFO reception 1/2 */ +#define LL_SPI_RX_FIFO_FULL (SPI_SR_FRLVL_1 | SPI_SR_FRLVL_0) /*!< FIFO reception full */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TX_FIFO TX FIFO Level + * @{ + */ +#define LL_SPI_TX_FIFO_EMPTY 0x00000000U /*!< FIFO transmission empty */ +#define LL_SPI_TX_FIFO_QUARTER_FULL (SPI_SR_FTLVL_0) /*!< FIFO transmission 1/4 */ +#define LL_SPI_TX_FIFO_HALF_FULL (SPI_SR_FTLVL_1) /*!< FIFO transmission 1/2 */ +#define LL_SPI_TX_FIFO_FULL (SPI_SR_FTLVL_1 | SPI_SR_FTLVL_0) /*!< FIFO transmission full */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DMA_PARITY DMA Parity + * @{ + */ +#define LL_SPI_DMA_PARITY_EVEN 0x00000000U /*!< Select DMA parity Even */ +#define LL_SPI_DMA_PARITY_ODD 0x00000001U /*!< Select DMA parity Odd */ + +/** + * @} + */ + +/** + * @} + */ + +/* 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 CR2 DS LL_SPI_SetDataWidth + * @param SPIx SPI Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_4BIT + * @arg @ref LL_SPI_DATAWIDTH_5BIT + * @arg @ref LL_SPI_DATAWIDTH_6BIT + * @arg @ref LL_SPI_DATAWIDTH_7BIT + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_9BIT + * @arg @ref LL_SPI_DATAWIDTH_10BIT + * @arg @ref LL_SPI_DATAWIDTH_11BIT + * @arg @ref LL_SPI_DATAWIDTH_12BIT + * @arg @ref LL_SPI_DATAWIDTH_13BIT + * @arg @ref LL_SPI_DATAWIDTH_14BIT + * @arg @ref LL_SPI_DATAWIDTH_15BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_DS, DataWidth); +} + +/** + * @brief Get frame data width + * @rmtoll CR2 DS LL_SPI_GetDataWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_4BIT + * @arg @ref LL_SPI_DATAWIDTH_5BIT + * @arg @ref LL_SPI_DATAWIDTH_6BIT + * @arg @ref LL_SPI_DATAWIDTH_7BIT + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_9BIT + * @arg @ref LL_SPI_DATAWIDTH_10BIT + * @arg @ref LL_SPI_DATAWIDTH_11BIT + * @arg @ref LL_SPI_DATAWIDTH_12BIT + * @arg @ref LL_SPI_DATAWIDTH_13BIT + * @arg @ref LL_SPI_DATAWIDTH_14BIT + * @arg @ref LL_SPI_DATAWIDTH_15BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_DS)); +} + +/** + * @brief Set threshold of RXFIFO that triggers an RXNE event + * @rmtoll CR2 FRXTH LL_SPI_SetRxFIFOThreshold + * @param SPIx SPI Instance + * @param Threshold This parameter can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_TH_HALF + * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetRxFIFOThreshold(SPI_TypeDef *SPIx, uint32_t Threshold) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_FRXTH, Threshold); +} + +/** + * @brief Get threshold of RXFIFO that triggers an RXNE event + * @rmtoll CR2 FRXTH LL_SPI_GetRxFIFOThreshold + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_TH_HALF + * @arg @ref LL_SPI_RX_FIFO_TH_QUARTER + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOThreshold(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRXTH)); +} + +/** + * @} + */ + +/** @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 CRC Length + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCL LL_SPI_SetCRCWidth + * @param SPIx SPI Instance + * @param CRCLength This parameter can be one of the following values: + * @arg @ref LL_SPI_CRC_8BIT + * @arg @ref LL_SPI_CRC_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCWidth(SPI_TypeDef *SPIx, uint32_t CRCLength) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CRCL, CRCLength); +} + +/** + * @brief Get CRC Length + * @rmtoll CR1 CRCL LL_SPI_GetCRCWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_CRC_8BIT + * @arg @ref LL_SPI_CRC_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CRCL)); +} + +/** + * @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); +} + +/** + * @brief Enable NSS pulse management + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_EnableNSSPulseMgt + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableNSSPulseMgt(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_NSSP); +} + +/** + * @brief Disable NSS pulse management + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_DisableNSSPulseMgt + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableNSSPulseMgt(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_NSSP); +} + +/** + * @brief Check if NSS pulse is enabled + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR2 NSSP LL_SPI_IsEnabledNSSPulse + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledNSSPulse(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_NSSP) == (SPI_CR2_NSSP)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @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 Get FIFO reception Level + * @rmtoll SR FRLVL LL_SPI_GetRxFIFOLevel + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_RX_FIFO_EMPTY + * @arg @ref LL_SPI_RX_FIFO_QUARTER_FULL + * @arg @ref LL_SPI_RX_FIFO_HALF_FULL + * @arg @ref LL_SPI_RX_FIFO_FULL + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxFIFOLevel(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FRLVL)); +} + +/** + * @brief Get FIFO Transmission Level + * @rmtoll SR FTLVL LL_SPI_GetTxFIFOLevel + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_TX_FIFO_EMPTY + * @arg @ref LL_SPI_TX_FIFO_QUARTER_FULL + * @arg @ref LL_SPI_TX_FIFO_HALF_FULL + * @arg @ref LL_SPI_TX_FIFO_FULL + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxFIFOLevel(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->SR, SPI_SR_FTLVL)); +} + +/** + * @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 Set parity of Last DMA reception + * @rmtoll CR2 LDMARX LL_SPI_SetDMAParity_RX + * @param SPIx SPI Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDMAParity_RX(SPI_TypeDef *SPIx, uint32_t Parity) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_LDMARX, (Parity << SPI_CR2_LDMARX_Pos)); +} + +/** + * @brief Get parity configuration for Last DMA reception + * @rmtoll CR2 LDMARX LL_SPI_GetDMAParity_RX + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + */ +__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_RX(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMARX) >> SPI_CR2_LDMARX_Pos); +} + +/** + * @brief Set parity of Last DMA transmission + * @rmtoll CR2 LDMATX LL_SPI_SetDMAParity_TX + * @param SPIx SPI Instance + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDMAParity_TX(SPI_TypeDef *SPIx, uint32_t Parity) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_LDMATX, (Parity << SPI_CR2_LDMATX_Pos)); +} + +/** + * @brief Get parity configuration for Last DMA transmission + * @rmtoll CR2 LDMATX LL_SPI_GetDMAParity_TX + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DMA_PARITY_ODD + * @arg @ref LL_SPI_DMA_PARITY_EVEN + */ +__STATIC_INLINE uint32_t LL_SPI_GetDMAParity_TX(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_LDMATX) >> SPI_CR2_LDMATX_Pos); +} + +/** + * @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 */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_SPI_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_system.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_system.h new file mode 100644 index 0000000..94b722b --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_system.h @@ -0,0 +1,1627 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_system.h + * @author MCD Application Team + * @brief Header file of SYSTEM 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. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The LL SYSTEM driver contains a set of generic APIs that can be + used by user: + (+) Some of the FLASH features need to be handled in the SYSTEM file. + (+) Access to DBGCMU registers + (+) Access to SYSCFG registers + (+) Access to VREFBUF registers + + @endverbatim + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32L4xx_LL_SYSTEM_H +#define STM32L4xx_LL_SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (FLASH) || defined (SYSCFG) || defined (DBGMCU) || defined (VREFBUF) + +/** @defgroup SYSTEM_LL SYSTEM + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SYSTEM_LL_Private_Constants SYSTEM Private Constants + * @{ + */ + +/** + * @brief Power-down in Run mode Flash key + */ +#define FLASH_PDKEY1 0x04152637U /*!< Flash power down key1 */ +#define FLASH_PDKEY2 0xFAFBFCFDU /*!< Flash power down key2: used with FLASH_PDKEY1 + to unlock the RUN_PD bit in FLASH_ACR */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SYSTEM_LL_Exported_Constants SYSTEM Exported Constants + * @{ + */ + +/** @defgroup SYSTEM_LL_EC_REMAP SYSCFG REMAP +* @{ +*/ +#define LL_SYSCFG_REMAP_FLASH 0x00000000U /*!< Main Flash memory mapped at 0x00000000 */ +#define LL_SYSCFG_REMAP_SYSTEMFLASH SYSCFG_MEMRMP_MEM_MODE_0 /*!< System Flash memory mapped at 0x00000000 */ +#define LL_SYSCFG_REMAP_SRAM (SYSCFG_MEMRMP_MEM_MODE_1 | SYSCFG_MEMRMP_MEM_MODE_0) /*!< SRAM1 mapped at 0x00000000 */ +#if defined(FMC_Bank1_R) +#define LL_SYSCFG_REMAP_FMC SYSCFG_MEMRMP_MEM_MODE_1 /*!< FMC bank 1 (NOR/PSRAM 1 and 2) mapped at 0x00000000 */ +#endif /* FMC_Bank1_R */ +#define LL_SYSCFG_REMAP_QUADSPI (SYSCFG_MEMRMP_MEM_MODE_2 | SYSCFG_MEMRMP_MEM_MODE_1) /*!< QUADSPI memory mapped at 0x00000000 */ +/** + * @} + */ + +#if defined(SYSCFG_MEMRMP_FB_MODE) +/** @defgroup SYSTEM_LL_EC_BANKMODE SYSCFG BANK MODE + * @{ + */ +#define LL_SYSCFG_BANKMODE_BANK1 0x00000000U /*!< Flash Bank1 mapped at 0x08000000 (and aliased @0x00000000) + and Flash Bank2 mapped at 0x08080000 (and aliased at 0x00080000) */ +#define LL_SYSCFG_BANKMODE_BANK2 SYSCFG_MEMRMP_FB_MODE /*!< Flash Bank2 mapped at 0x08000000 (and aliased @0x00000000) + and Flash Bank1 mapped at 0x08080000 (and aliased at 0x00080000) */ +/** + * @} + */ + +#endif /* SYSCFG_MEMRMP_FB_MODE */ +/** @defgroup SYSTEM_LL_EC_I2C_FASTMODEPLUS SYSCFG I2C FASTMODEPLUS + * @{ + */ +#define LL_SYSCFG_I2C_FASTMODEPLUS_PB6 SYSCFG_CFGR1_I2C_PB6_FMP /*!< Enable Fast Mode Plus on PB6 */ +#define LL_SYSCFG_I2C_FASTMODEPLUS_PB7 SYSCFG_CFGR1_I2C_PB7_FMP /*!< Enable Fast Mode Plus on PB7 */ +#if defined(SYSCFG_CFGR1_I2C_PB8_FMP) +#define LL_SYSCFG_I2C_FASTMODEPLUS_PB8 SYSCFG_CFGR1_I2C_PB8_FMP /*!< Enable Fast Mode Plus on PB8 */ +#endif /* SYSCFG_CFGR1_I2C_PB8_FMP */ +#if defined(SYSCFG_CFGR1_I2C_PB9_FMP) +#define LL_SYSCFG_I2C_FASTMODEPLUS_PB9 SYSCFG_CFGR1_I2C_PB9_FMP /*!< Enable Fast Mode Plus on PB9 */ +#endif /* SYSCFG_CFGR1_I2C_PB9_FMP */ +#define LL_SYSCFG_I2C_FASTMODEPLUS_I2C1 SYSCFG_CFGR1_I2C1_FMP /*!< Enable Fast Mode Plus on I2C1 pins */ +#if defined(I2C2) +#define LL_SYSCFG_I2C_FASTMODEPLUS_I2C2 SYSCFG_CFGR1_I2C2_FMP /*!< Enable Fast Mode Plus on I2C2 pins */ +#endif /* I2C2 */ +#define LL_SYSCFG_I2C_FASTMODEPLUS_I2C3 SYSCFG_CFGR1_I2C3_FMP /*!< Enable Fast Mode Plus on I2C3 pins */ +#if defined(I2C4) +#define LL_SYSCFG_I2C_FASTMODEPLUS_I2C4 SYSCFG_CFGR1_I2C4_FMP /*!< Enable Fast Mode Plus on I2C4 pins */ +#endif /* I2C4 */ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_EXTI_PORT SYSCFG EXTI PORT + * @{ + */ +#define LL_SYSCFG_EXTI_PORTA 0U /*!< EXTI PORT A */ +#define LL_SYSCFG_EXTI_PORTB 1U /*!< EXTI PORT B */ +#define LL_SYSCFG_EXTI_PORTC 2U /*!< EXTI PORT C */ +#define LL_SYSCFG_EXTI_PORTD 3U /*!< EXTI PORT D */ +#define LL_SYSCFG_EXTI_PORTE 4U /*!< EXTI PORT E */ +#if defined(GPIOF) +#define LL_SYSCFG_EXTI_PORTF 5U /*!< EXTI PORT F */ +#endif /* GPIOF */ +#if defined(GPIOG) +#define LL_SYSCFG_EXTI_PORTG 6U /*!< EXTI PORT G */ +#endif /* GPIOG */ +#define LL_SYSCFG_EXTI_PORTH 7U /*!< EXTI PORT H */ +#if defined(GPIOI) +#define LL_SYSCFG_EXTI_PORTI 8U /*!< EXTI PORT I */ +#endif /* GPIOI */ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_EXTI_LINE SYSCFG EXTI LINE + * @{ + */ +#define LL_SYSCFG_EXTI_LINE0 (uint32_t)(0x000FU << 16U | 0U) /* !< EXTI_POSITION_0 | EXTICR[0] */ +#define LL_SYSCFG_EXTI_LINE1 (uint32_t)(0x00F0U << 16U | 0U) /* !< EXTI_POSITION_4 | EXTICR[0] */ +#define LL_SYSCFG_EXTI_LINE2 (uint32_t)(0x0F00U << 16U | 0U) /* !< EXTI_POSITION_8 | EXTICR[0] */ +#define LL_SYSCFG_EXTI_LINE3 (uint32_t)(0xF000U << 16U | 0U) /* !< EXTI_POSITION_12 | EXTICR[0] */ +#define LL_SYSCFG_EXTI_LINE4 (uint32_t)(0x000FU << 16U | 1U) /* !< EXTI_POSITION_0 | EXTICR[1] */ +#define LL_SYSCFG_EXTI_LINE5 (uint32_t)(0x00F0U << 16U | 1U) /* !< EXTI_POSITION_4 | EXTICR[1] */ +#define LL_SYSCFG_EXTI_LINE6 (uint32_t)(0x0F00U << 16U | 1U) /* !< EXTI_POSITION_8 | EXTICR[1] */ +#define LL_SYSCFG_EXTI_LINE7 (uint32_t)(0xF000U << 16U | 1U) /* !< EXTI_POSITION_12 | EXTICR[1] */ +#define LL_SYSCFG_EXTI_LINE8 (uint32_t)(0x000FU << 16U | 2U) /* !< EXTI_POSITION_0 | EXTICR[2] */ +#define LL_SYSCFG_EXTI_LINE9 (uint32_t)(0x00F0U << 16U | 2U) /* !< EXTI_POSITION_4 | EXTICR[2] */ +#define LL_SYSCFG_EXTI_LINE10 (uint32_t)(0x0F00U << 16U | 2U) /* !< EXTI_POSITION_8 | EXTICR[2] */ +#define LL_SYSCFG_EXTI_LINE11 (uint32_t)(0xF000U << 16U | 2U) /* !< EXTI_POSITION_12 | EXTICR[2] */ +#define LL_SYSCFG_EXTI_LINE12 (uint32_t)(0x000FU << 16U | 3U) /* !< EXTI_POSITION_0 | EXTICR[3] */ +#define LL_SYSCFG_EXTI_LINE13 (uint32_t)(0x00F0U << 16U | 3U) /* !< EXTI_POSITION_4 | EXTICR[3] */ +#define LL_SYSCFG_EXTI_LINE14 (uint32_t)(0x0F00U << 16U | 3U) /* !< EXTI_POSITION_8 | EXTICR[3] */ +#define LL_SYSCFG_EXTI_LINE15 (uint32_t)(0xF000U << 16U | 3U) /* !< EXTI_POSITION_12 | EXTICR[3] */ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_TIMBREAK SYSCFG TIMER BREAK + * @{ + */ +#define LL_SYSCFG_TIMBREAK_ECC SYSCFG_CFGR2_ECCL /*!< Enables and locks the ECC error signal + with Break Input of TIM1/8/15/16/17 */ +#define LL_SYSCFG_TIMBREAK_PVD SYSCFG_CFGR2_PVDL /*!< Enables and locks the PVD connection + with TIM1/8/15/16/17 Break Input + and also the PVDE and PLS bits of the Power Control Interface */ +#define LL_SYSCFG_TIMBREAK_SRAM2_PARITY SYSCFG_CFGR2_SPL /*!< Enables and locks the SRAM2_PARITY error signal + with Break Input of TIM1/8/15/16/17 */ +#define LL_SYSCFG_TIMBREAK_LOCKUP SYSCFG_CFGR2_CLL /*!< Enables and locks the LOCKUP output of CortexM4 + with Break Input of TIM1/15/16/17 */ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_SRAM2WRP SYSCFG SRAM2 WRP + * @{ + */ +#define LL_SYSCFG_SRAM2WRP_PAGE0 SYSCFG_SWPR_PAGE0 /*!< SRAM2 Write protection page 0 */ +#define LL_SYSCFG_SRAM2WRP_PAGE1 SYSCFG_SWPR_PAGE1 /*!< SRAM2 Write protection page 1 */ +#define LL_SYSCFG_SRAM2WRP_PAGE2 SYSCFG_SWPR_PAGE2 /*!< SRAM2 Write protection page 2 */ +#define LL_SYSCFG_SRAM2WRP_PAGE3 SYSCFG_SWPR_PAGE3 /*!< SRAM2 Write protection page 3 */ +#define LL_SYSCFG_SRAM2WRP_PAGE4 SYSCFG_SWPR_PAGE4 /*!< SRAM2 Write protection page 4 */ +#define LL_SYSCFG_SRAM2WRP_PAGE5 SYSCFG_SWPR_PAGE5 /*!< SRAM2 Write protection page 5 */ +#define LL_SYSCFG_SRAM2WRP_PAGE6 SYSCFG_SWPR_PAGE6 /*!< SRAM2 Write protection page 6 */ +#define LL_SYSCFG_SRAM2WRP_PAGE7 SYSCFG_SWPR_PAGE7 /*!< SRAM2 Write protection page 7 */ +#define LL_SYSCFG_SRAM2WRP_PAGE8 SYSCFG_SWPR_PAGE8 /*!< SRAM2 Write protection page 8 */ +#define LL_SYSCFG_SRAM2WRP_PAGE9 SYSCFG_SWPR_PAGE9 /*!< SRAM2 Write protection page 9 */ +#define LL_SYSCFG_SRAM2WRP_PAGE10 SYSCFG_SWPR_PAGE10 /*!< SRAM2 Write protection page 10 */ +#define LL_SYSCFG_SRAM2WRP_PAGE11 SYSCFG_SWPR_PAGE11 /*!< SRAM2 Write protection page 11 */ +#define LL_SYSCFG_SRAM2WRP_PAGE12 SYSCFG_SWPR_PAGE12 /*!< SRAM2 Write protection page 12 */ +#define LL_SYSCFG_SRAM2WRP_PAGE13 SYSCFG_SWPR_PAGE13 /*!< SRAM2 Write protection page 13 */ +#define LL_SYSCFG_SRAM2WRP_PAGE14 SYSCFG_SWPR_PAGE14 /*!< SRAM2 Write protection page 14 */ +#define LL_SYSCFG_SRAM2WRP_PAGE15 SYSCFG_SWPR_PAGE15 /*!< SRAM2 Write protection page 15 */ +#if defined(SYSCFG_SWPR_PAGE31) +#define LL_SYSCFG_SRAM2WRP_PAGE16 SYSCFG_SWPR_PAGE16 /*!< SRAM2 Write protection page 16 */ +#define LL_SYSCFG_SRAM2WRP_PAGE17 SYSCFG_SWPR_PAGE17 /*!< SRAM2 Write protection page 17 */ +#define LL_SYSCFG_SRAM2WRP_PAGE18 SYSCFG_SWPR_PAGE18 /*!< SRAM2 Write protection page 18 */ +#define LL_SYSCFG_SRAM2WRP_PAGE19 SYSCFG_SWPR_PAGE19 /*!< SRAM2 Write protection page 19 */ +#define LL_SYSCFG_SRAM2WRP_PAGE20 SYSCFG_SWPR_PAGE20 /*!< SRAM2 Write protection page 20 */ +#define LL_SYSCFG_SRAM2WRP_PAGE21 SYSCFG_SWPR_PAGE21 /*!< SRAM2 Write protection page 21 */ +#define LL_SYSCFG_SRAM2WRP_PAGE22 SYSCFG_SWPR_PAGE22 /*!< SRAM2 Write protection page 22 */ +#define LL_SYSCFG_SRAM2WRP_PAGE23 SYSCFG_SWPR_PAGE23 /*!< SRAM2 Write protection page 23 */ +#define LL_SYSCFG_SRAM2WRP_PAGE24 SYSCFG_SWPR_PAGE24 /*!< SRAM2 Write protection page 24 */ +#define LL_SYSCFG_SRAM2WRP_PAGE25 SYSCFG_SWPR_PAGE25 /*!< SRAM2 Write protection page 25 */ +#define LL_SYSCFG_SRAM2WRP_PAGE26 SYSCFG_SWPR_PAGE26 /*!< SRAM2 Write protection page 26 */ +#define LL_SYSCFG_SRAM2WRP_PAGE27 SYSCFG_SWPR_PAGE27 /*!< SRAM2 Write protection page 27 */ +#define LL_SYSCFG_SRAM2WRP_PAGE28 SYSCFG_SWPR_PAGE28 /*!< SRAM2 Write protection page 28 */ +#define LL_SYSCFG_SRAM2WRP_PAGE29 SYSCFG_SWPR_PAGE29 /*!< SRAM2 Write protection page 29 */ +#define LL_SYSCFG_SRAM2WRP_PAGE30 SYSCFG_SWPR_PAGE30 /*!< SRAM2 Write protection page 30 */ +#define LL_SYSCFG_SRAM2WRP_PAGE31 SYSCFG_SWPR_PAGE31 /*!< SRAM2 Write protection page 31 */ +#endif /* SYSCFG_SWPR_PAGE31 */ +#if defined(SYSCFG_SWPR2_PAGE63) +#define LL_SYSCFG_SRAM2WRP_PAGE32 SYSCFG_SWPR2_PAGE32 /*!< SRAM2 Write protection page 32 */ +#define LL_SYSCFG_SRAM2WRP_PAGE33 SYSCFG_SWPR2_PAGE33 /*!< SRAM2 Write protection page 33 */ +#define LL_SYSCFG_SRAM2WRP_PAGE34 SYSCFG_SWPR2_PAGE34 /*!< SRAM2 Write protection page 34 */ +#define LL_SYSCFG_SRAM2WRP_PAGE35 SYSCFG_SWPR2_PAGE35 /*!< SRAM2 Write protection page 35 */ +#define LL_SYSCFG_SRAM2WRP_PAGE36 SYSCFG_SWPR2_PAGE36 /*!< SRAM2 Write protection page 36 */ +#define LL_SYSCFG_SRAM2WRP_PAGE37 SYSCFG_SWPR2_PAGE37 /*!< SRAM2 Write protection page 37 */ +#define LL_SYSCFG_SRAM2WRP_PAGE38 SYSCFG_SWPR2_PAGE38 /*!< SRAM2 Write protection page 38 */ +#define LL_SYSCFG_SRAM2WRP_PAGE39 SYSCFG_SWPR2_PAGE39 /*!< SRAM2 Write protection page 39 */ +#define LL_SYSCFG_SRAM2WRP_PAGE40 SYSCFG_SWPR2_PAGE40 /*!< SRAM2 Write protection page 40 */ +#define LL_SYSCFG_SRAM2WRP_PAGE41 SYSCFG_SWPR2_PAGE41 /*!< SRAM2 Write protection page 41 */ +#define LL_SYSCFG_SRAM2WRP_PAGE42 SYSCFG_SWPR2_PAGE42 /*!< SRAM2 Write protection page 42 */ +#define LL_SYSCFG_SRAM2WRP_PAGE43 SYSCFG_SWPR2_PAGE43 /*!< SRAM2 Write protection page 43 */ +#define LL_SYSCFG_SRAM2WRP_PAGE44 SYSCFG_SWPR2_PAGE44 /*!< SRAM2 Write protection page 44 */ +#define LL_SYSCFG_SRAM2WRP_PAGE45 SYSCFG_SWPR2_PAGE45 /*!< SRAM2 Write protection page 45 */ +#define LL_SYSCFG_SRAM2WRP_PAGE46 SYSCFG_SWPR2_PAGE46 /*!< SRAM2 Write protection page 46 */ +#define LL_SYSCFG_SRAM2WRP_PAGE47 SYSCFG_SWPR2_PAGE47 /*!< SRAM2 Write protection page 47 */ +#define LL_SYSCFG_SRAM2WRP_PAGE48 SYSCFG_SWPR2_PAGE48 /*!< SRAM2 Write protection page 48 */ +#define LL_SYSCFG_SRAM2WRP_PAGE49 SYSCFG_SWPR2_PAGE49 /*!< SRAM2 Write protection page 49 */ +#define LL_SYSCFG_SRAM2WRP_PAGE50 SYSCFG_SWPR2_PAGE50 /*!< SRAM2 Write protection page 50 */ +#define LL_SYSCFG_SRAM2WRP_PAGE51 SYSCFG_SWPR2_PAGE51 /*!< SRAM2 Write protection page 51 */ +#define LL_SYSCFG_SRAM2WRP_PAGE52 SYSCFG_SWPR2_PAGE52 /*!< SRAM2 Write protection page 52 */ +#define LL_SYSCFG_SRAM2WRP_PAGE53 SYSCFG_SWPR2_PAGE53 /*!< SRAM2 Write protection page 53 */ +#define LL_SYSCFG_SRAM2WRP_PAGE54 SYSCFG_SWPR2_PAGE54 /*!< SRAM2 Write protection page 54 */ +#define LL_SYSCFG_SRAM2WRP_PAGE55 SYSCFG_SWPR2_PAGE55 /*!< SRAM2 Write protection page 55 */ +#define LL_SYSCFG_SRAM2WRP_PAGE56 SYSCFG_SWPR2_PAGE56 /*!< SRAM2 Write protection page 56 */ +#define LL_SYSCFG_SRAM2WRP_PAGE57 SYSCFG_SWPR2_PAGE57 /*!< SRAM2 Write protection page 57 */ +#define LL_SYSCFG_SRAM2WRP_PAGE58 SYSCFG_SWPR2_PAGE58 /*!< SRAM2 Write protection page 58 */ +#define LL_SYSCFG_SRAM2WRP_PAGE59 SYSCFG_SWPR2_PAGE59 /*!< SRAM2 Write protection page 59 */ +#define LL_SYSCFG_SRAM2WRP_PAGE60 SYSCFG_SWPR2_PAGE60 /*!< SRAM2 Write protection page 60 */ +#define LL_SYSCFG_SRAM2WRP_PAGE61 SYSCFG_SWPR2_PAGE61 /*!< SRAM2 Write protection page 61 */ +#define LL_SYSCFG_SRAM2WRP_PAGE62 SYSCFG_SWPR2_PAGE62 /*!< SRAM2 Write protection page 62 */ +#define LL_SYSCFG_SRAM2WRP_PAGE63 SYSCFG_SWPR2_PAGE63 /*!< SRAM2 Write protection page 63 */ +#endif /* SYSCFG_SWPR2_PAGE63 */ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_TRACE DBGMCU TRACE Pin Assignment + * @{ + */ +#define LL_DBGMCU_TRACE_NONE 0x00000000U /*!< TRACE pins not assigned (default state) */ +#define LL_DBGMCU_TRACE_ASYNCH DBGMCU_CR_TRACE_IOEN /*!< TRACE pin assignment for Asynchronous Mode */ +#define LL_DBGMCU_TRACE_SYNCH_SIZE1 (DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE_0) /*!< TRACE pin assignment for Synchronous Mode with a TRACEDATA size of 1 */ +#define LL_DBGMCU_TRACE_SYNCH_SIZE2 (DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE_1) /*!< TRACE pin assignment for Synchronous Mode with a TRACEDATA size of 2 */ +#define LL_DBGMCU_TRACE_SYNCH_SIZE4 (DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE) /*!< TRACE pin assignment for Synchronous Mode with a TRACEDATA size of 4 */ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_APB1_GRP1_STOP_IP DBGMCU APB1 GRP1 STOP IP + * @{ + */ +#define LL_DBGMCU_APB1_GRP1_TIM2_STOP DBGMCU_APB1FZR1_DBG_TIM2_STOP /*!< The counter clock of TIM2 is stopped when the core is halted*/ +#if defined(TIM3) +#define LL_DBGMCU_APB1_GRP1_TIM3_STOP DBGMCU_APB1FZR1_DBG_TIM3_STOP /*!< The counter clock of TIM3 is stopped when the core is halted*/ +#endif /* TIM3 */ +#if defined(TIM4) +#define LL_DBGMCU_APB1_GRP1_TIM4_STOP DBGMCU_APB1FZR1_DBG_TIM4_STOP /*!< The counter clock of TIM4 is stopped when the core is halted*/ +#endif /* TIM4 */ +#if defined(TIM5) +#define LL_DBGMCU_APB1_GRP1_TIM5_STOP DBGMCU_APB1FZR1_DBG_TIM5_STOP /*!< The counter clock of TIM5 is stopped when the core is halted*/ +#endif /* TIM5 */ +#define LL_DBGMCU_APB1_GRP1_TIM6_STOP DBGMCU_APB1FZR1_DBG_TIM6_STOP /*!< The counter clock of TIM6 is stopped when the core is halted*/ +#if defined(TIM7) +#define LL_DBGMCU_APB1_GRP1_TIM7_STOP DBGMCU_APB1FZR1_DBG_TIM7_STOP /*!< The counter clock of TIM7 is stopped when the core is halted*/ +#endif /* TIM7 */ +#define LL_DBGMCU_APB1_GRP1_RTC_STOP DBGMCU_APB1FZR1_DBG_RTC_STOP /*!< The clock of the RTC counter is stopped when the core is halted*/ +#define LL_DBGMCU_APB1_GRP1_WWDG_STOP DBGMCU_APB1FZR1_DBG_WWDG_STOP /*!< The window watchdog counter clock is stopped when the core is halted*/ +#define LL_DBGMCU_APB1_GRP1_IWDG_STOP DBGMCU_APB1FZR1_DBG_IWDG_STOP /*!< The independent watchdog counter clock is stopped when the core is halted*/ +#define LL_DBGMCU_APB1_GRP1_I2C1_STOP DBGMCU_APB1FZR1_DBG_I2C1_STOP /*!< The I2C1 SMBus timeout is frozen*/ +#if defined(I2C2) +#define LL_DBGMCU_APB1_GRP1_I2C2_STOP DBGMCU_APB1FZR1_DBG_I2C2_STOP /*!< The I2C2 SMBus timeout is frozen*/ +#endif /* I2C2 */ +#define LL_DBGMCU_APB1_GRP1_I2C3_STOP DBGMCU_APB1FZR1_DBG_I2C3_STOP /*!< The I2C3 SMBus timeout is frozen*/ +#define LL_DBGMCU_APB1_GRP1_CAN_STOP DBGMCU_APB1FZR1_DBG_CAN_STOP /*!< The bxCAN receive registers are frozen*/ +#if defined(CAN2) +#define LL_DBGMCU_APB1_GRP1_CAN2_STOP DBGMCU_APB1FZR1_DBG_CAN2_STOP /*!< The bxCAN2 receive registers are frozen*/ +#endif /* CAN2 */ +#define LL_DBGMCU_APB1_GRP1_LPTIM1_STOP DBGMCU_APB1FZR1_DBG_LPTIM1_STOP /*!< The counter clock of LPTIM1 is stopped when the core is halted*/ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_APB1_GRP2_STOP_IP DBGMCU APB1 GRP2 STOP IP + * @{ + */ +#if defined(I2C4) +#define LL_DBGMCU_APB1_GRP2_I2C4_STOP DBGMCU_APB1FZR2_DBG_I2C4_STOP /*!< The I2C4 SMBus timeout is frozen*/ +#endif /* I2C4 */ +#define LL_DBGMCU_APB1_GRP2_LPTIM2_STOP DBGMCU_APB1FZR2_DBG_LPTIM2_STOP /*!< The counter clock of LPTIM2 is stopped when the core is halted*/ +/** + * @} + */ + +/** @defgroup SYSTEM_LL_EC_APB2_GRP1_STOP_IP DBGMCU APB2 GRP1 STOP IP + * @{ + */ +#define LL_DBGMCU_APB2_GRP1_TIM1_STOP DBGMCU_APB2FZ_DBG_TIM1_STOP /*!< The counter clock of TIM1 is stopped when the core is halted*/ +#if defined(TIM8) +#define LL_DBGMCU_APB2_GRP1_TIM8_STOP DBGMCU_APB2FZ_DBG_TIM8_STOP /*!< The counter clock of TIM8 is stopped when the core is halted*/ +#endif /* TIM8 */ +#define LL_DBGMCU_APB2_GRP1_TIM15_STOP DBGMCU_APB2FZ_DBG_TIM15_STOP /*!< The counter clock of TIM15 is stopped when the core is halted*/ +#define LL_DBGMCU_APB2_GRP1_TIM16_STOP DBGMCU_APB2FZ_DBG_TIM16_STOP /*!< The counter clock of TIM16 is stopped when the core is halted*/ +#if defined(TIM17) +#define LL_DBGMCU_APB2_GRP1_TIM17_STOP DBGMCU_APB2FZ_DBG_TIM17_STOP /*!< The counter clock of TIM17 is stopped when the core is halted*/ +#endif /* TIM17 */ +/** + * @} + */ + +#if defined(VREFBUF) +/** @defgroup SYSTEM_LL_EC_VOLTAGE VREFBUF VOLTAGE + * @{ + */ +#define LL_VREFBUF_VOLTAGE_SCALE0 ((uint32_t)0x00000000) /*!< Voltage reference scale 0 (VREF_OUT1) */ +#define LL_VREFBUF_VOLTAGE_SCALE1 VREFBUF_CSR_VRS /*!< Voltage reference scale 1 (VREF_OUT2) */ +/** + * @} + */ +#endif /* VREFBUF */ + +/** @defgroup SYSTEM_LL_EC_LATENCY FLASH LATENCY + * @{ + */ +#define LL_FLASH_LATENCY_0 FLASH_ACR_LATENCY_0WS /*!< FLASH Zero wait state */ +#define LL_FLASH_LATENCY_1 FLASH_ACR_LATENCY_1WS /*!< FLASH One wait state */ +#define LL_FLASH_LATENCY_2 FLASH_ACR_LATENCY_2WS /*!< FLASH Two wait states */ +#define LL_FLASH_LATENCY_3 FLASH_ACR_LATENCY_3WS /*!< FLASH Three wait states */ +#define LL_FLASH_LATENCY_4 FLASH_ACR_LATENCY_4WS /*!< FLASH Four wait states */ +#if defined(FLASH_ACR_LATENCY_5WS) +#define LL_FLASH_LATENCY_5 FLASH_ACR_LATENCY_5WS /*!< FLASH five wait state */ +#define LL_FLASH_LATENCY_6 FLASH_ACR_LATENCY_6WS /*!< FLASH six wait state */ +#define LL_FLASH_LATENCY_7 FLASH_ACR_LATENCY_7WS /*!< FLASH seven wait states */ +#define LL_FLASH_LATENCY_8 FLASH_ACR_LATENCY_8WS /*!< FLASH eight wait states */ +#define LL_FLASH_LATENCY_9 FLASH_ACR_LATENCY_9WS /*!< FLASH nine wait states */ +#define LL_FLASH_LATENCY_10 FLASH_ACR_LATENCY_10WS /*!< FLASH ten wait states */ +#define LL_FLASH_LATENCY_11 FLASH_ACR_LATENCY_11WS /*!< FLASH eleven wait states */ +#define LL_FLASH_LATENCY_12 FLASH_ACR_LATENCY_12WS /*!< FLASH twelve wait states */ +#define LL_FLASH_LATENCY_13 FLASH_ACR_LATENCY_13WS /*!< FLASH thirteen wait states */ +#define LL_FLASH_LATENCY_14 FLASH_ACR_LATENCY_14WS /*!< FLASH fourteen wait states */ +#define LL_FLASH_LATENCY_15 FLASH_ACR_LATENCY_15WS /*!< FLASH fifteen wait states */ +#endif +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SYSTEM_LL_Exported_Functions SYSTEM Exported Functions + * @{ + */ + +/** @defgroup SYSTEM_LL_EF_SYSCFG SYSCFG + * @{ + */ + +/** + * @brief Set memory mapping at address 0x00000000 + * @rmtoll SYSCFG_MEMRMP MEM_MODE LL_SYSCFG_SetRemapMemory + * @param Memory This parameter can be one of the following values: + * @arg @ref LL_SYSCFG_REMAP_FLASH + * @arg @ref LL_SYSCFG_REMAP_SYSTEMFLASH + * @arg @ref LL_SYSCFG_REMAP_SRAM + * @arg @ref LL_SYSCFG_REMAP_FMC (*) + * @arg @ref LL_SYSCFG_REMAP_QUADSPI + * + * (*) value not defined in all devices + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_SetRemapMemory(uint32_t Memory) +{ + MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE, Memory); +} + +/** + * @brief Get memory mapping at address 0x00000000 + * @rmtoll SYSCFG_MEMRMP MEM_MODE LL_SYSCFG_GetRemapMemory + * @retval Returned value can be one of the following values: + * @arg @ref LL_SYSCFG_REMAP_FLASH + * @arg @ref LL_SYSCFG_REMAP_SYSTEMFLASH + * @arg @ref LL_SYSCFG_REMAP_SRAM + * @arg @ref LL_SYSCFG_REMAP_FMC (*) + * @arg @ref LL_SYSCFG_REMAP_QUADSPI + * + * (*) value not defined in all devices + */ +__STATIC_INLINE uint32_t LL_SYSCFG_GetRemapMemory(void) +{ + return (uint32_t)(READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE)); +} + +#if defined(SYSCFG_MEMRMP_FB_MODE) +/** + * @brief Select Flash bank mode (Bank flashed at 0x08000000) + * @rmtoll SYSCFG_MEMRMP FB_MODE LL_SYSCFG_SetFlashBankMode + * @param Bank This parameter can be one of the following values: + * @arg @ref LL_SYSCFG_BANKMODE_BANK1 + * @arg @ref LL_SYSCFG_BANKMODE_BANK2 + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_SetFlashBankMode(uint32_t Bank) +{ + MODIFY_REG(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE, Bank); +} + +/** + * @brief Get Flash bank mode (Bank flashed at 0x08000000) + * @rmtoll SYSCFG_MEMRMP FB_MODE LL_SYSCFG_GetFlashBankMode + * @retval Returned value can be one of the following values: + * @arg @ref LL_SYSCFG_BANKMODE_BANK1 + * @arg @ref LL_SYSCFG_BANKMODE_BANK2 + */ +__STATIC_INLINE uint32_t LL_SYSCFG_GetFlashBankMode(void) +{ + return (uint32_t)(READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE)); +} +#endif /* SYSCFG_MEMRMP_FB_MODE */ + +/** + * @brief Firewall protection enabled + * @rmtoll SYSCFG_CFGR1 FWDIS LL_SYSCFG_EnableFirewall + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableFirewall(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FWDIS); +} + +/** + * @brief Check if Firewall protection is enabled or not + * @rmtoll SYSCFG_CFGR1 FWDIS LL_SYSCFG_IsEnabledFirewall + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledFirewall(void) +{ + return !(READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FWDIS) == SYSCFG_CFGR1_FWDIS); +} + +/** + * @brief Enable I/O analog switch voltage booster. + * @note When voltage booster is enabled, I/O analog switches are supplied + * by a dedicated voltage booster, from VDD power domain. This is + * the recommended configuration with low VDDA voltage operation. + * @note The I/O analog switch voltage booster is relevant for peripherals + * using I/O in analog input: ADC, COMP, OPAMP. + * However, COMP and OPAMP inputs have a high impedance and + * voltage booster do not impact performance significantly. + * Therefore, the voltage booster is mainly intended for + * usage with ADC. + * @rmtoll SYSCFG_CFGR1 BOOSTEN LL_SYSCFG_EnableAnalogBooster + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableAnalogBooster(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN); +} + +/** + * @brief Disable I/O analog switch voltage booster. + * @note When voltage booster is enabled, I/O analog switches are supplied + * by a dedicated voltage booster, from VDD power domain. This is + * the recommended configuration with low VDDA voltage operation. + * @note The I/O analog switch voltage booster is relevant for peripherals + * using I/O in analog input: ADC, COMP, OPAMP. + * However, COMP and OPAMP inputs have a high impedance and + * voltage booster do not impact performance significantly. + * Therefore, the voltage booster is mainly intended for + * usage with ADC. + * @rmtoll SYSCFG_CFGR1 BOOSTEN LL_SYSCFG_DisableAnalogBooster + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableAnalogBooster(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN); +} + +/** + * @brief Enable the I2C fast mode plus driving capability. + * @rmtoll SYSCFG_CFGR1 I2C_PBx_FMP LL_SYSCFG_EnableFastModePlus\n + * SYSCFG_CFGR1 I2Cx_FMP LL_SYSCFG_EnableFastModePlus + * @param ConfigFastModePlus This parameter can be a combination of the following values: + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB6 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB7 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB8 (*) + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB9 (*) + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C1 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C2 (*) + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C3 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C4 (*) + * + * (*) value not defined in all devices + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableFastModePlus(uint32_t ConfigFastModePlus) +{ + SET_BIT(SYSCFG->CFGR1, ConfigFastModePlus); +} + +/** + * @brief Disable the I2C fast mode plus driving capability. + * @rmtoll SYSCFG_CFGR1 I2C_PBx_FMP LL_SYSCFG_DisableFastModePlus\n + * SYSCFG_CFGR1 I2Cx_FMP LL_SYSCFG_DisableFastModePlus + * @param ConfigFastModePlus This parameter can be a combination of the following values: + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB6 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB7 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB8 (*) + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_PB9 (*) + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C1 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C2 (*) + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C3 + * @arg @ref LL_SYSCFG_I2C_FASTMODEPLUS_I2C4 (*) + * + * (*) value not defined in all devices + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableFastModePlus(uint32_t ConfigFastModePlus) +{ + CLEAR_BIT(SYSCFG->CFGR1, ConfigFastModePlus); +} + +/** + * @brief Enable Floating Point Unit Invalid operation Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_0 LL_SYSCFG_EnableIT_FPU_IOC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableIT_FPU_IOC(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_0); +} + +/** + * @brief Enable Floating Point Unit Divide-by-zero Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_1 LL_SYSCFG_EnableIT_FPU_DZC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableIT_FPU_DZC(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_1); +} + +/** + * @brief Enable Floating Point Unit Underflow Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_2 LL_SYSCFG_EnableIT_FPU_UFC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableIT_FPU_UFC(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_2); +} + +/** + * @brief Enable Floating Point Unit Overflow Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_3 LL_SYSCFG_EnableIT_FPU_OFC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableIT_FPU_OFC(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_3); +} + +/** + * @brief Enable Floating Point Unit Input denormal Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_4 LL_SYSCFG_EnableIT_FPU_IDC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableIT_FPU_IDC(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_4); +} + +/** + * @brief Enable Floating Point Unit Inexact Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_5 LL_SYSCFG_EnableIT_FPU_IXC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableIT_FPU_IXC(void) +{ + SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_5); +} + +/** + * @brief Disable Floating Point Unit Invalid operation Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_0 LL_SYSCFG_DisableIT_FPU_IOC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableIT_FPU_IOC(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_0); +} + +/** + * @brief Disable Floating Point Unit Divide-by-zero Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_1 LL_SYSCFG_DisableIT_FPU_DZC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableIT_FPU_DZC(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_1); +} + +/** + * @brief Disable Floating Point Unit Underflow Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_2 LL_SYSCFG_DisableIT_FPU_UFC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableIT_FPU_UFC(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_2); +} + +/** + * @brief Disable Floating Point Unit Overflow Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_3 LL_SYSCFG_DisableIT_FPU_OFC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableIT_FPU_OFC(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_3); +} + +/** + * @brief Disable Floating Point Unit Input denormal Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_4 LL_SYSCFG_DisableIT_FPU_IDC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableIT_FPU_IDC(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_4); +} + +/** + * @brief Disable Floating Point Unit Inexact Interrupt + * @rmtoll SYSCFG_CFGR1 FPU_IE_5 LL_SYSCFG_DisableIT_FPU_IXC + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_DisableIT_FPU_IXC(void) +{ + CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_5); +} + +/** + * @brief Check if Floating Point Unit Invalid operation Interrupt source is enabled or disabled. + * @rmtoll SYSCFG_CFGR1 FPU_IE_0 LL_SYSCFG_IsEnabledIT_FPU_IOC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledIT_FPU_IOC(void) +{ + return (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_0) == (SYSCFG_CFGR1_FPU_IE_0)); +} + +/** + * @brief Check if Floating Point Unit Divide-by-zero Interrupt source is enabled or disabled. + * @rmtoll SYSCFG_CFGR1 FPU_IE_1 LL_SYSCFG_IsEnabledIT_FPU_DZC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledIT_FPU_DZC(void) +{ + return (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_1) == (SYSCFG_CFGR1_FPU_IE_1)); +} + +/** + * @brief Check if Floating Point Unit Underflow Interrupt source is enabled or disabled. + * @rmtoll SYSCFG_CFGR1 FPU_IE_2 LL_SYSCFG_IsEnabledIT_FPU_UFC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledIT_FPU_UFC(void) +{ + return (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_2) == (SYSCFG_CFGR1_FPU_IE_2)); +} + +/** + * @brief Check if Floating Point Unit Overflow Interrupt source is enabled or disabled. + * @rmtoll SYSCFG_CFGR1 FPU_IE_3 LL_SYSCFG_IsEnabledIT_FPU_OFC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledIT_FPU_OFC(void) +{ + return (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_3) == (SYSCFG_CFGR1_FPU_IE_3)); +} + +/** + * @brief Check if Floating Point Unit Input denormal Interrupt source is enabled or disabled. + * @rmtoll SYSCFG_CFGR1 FPU_IE_4 LL_SYSCFG_IsEnabledIT_FPU_IDC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledIT_FPU_IDC(void) +{ + return (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_4) == (SYSCFG_CFGR1_FPU_IE_4)); +} + +/** + * @brief Check if Floating Point Unit Inexact Interrupt source is enabled or disabled. + * @rmtoll SYSCFG_CFGR1 FPU_IE_5 LL_SYSCFG_IsEnabledIT_FPU_IXC + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsEnabledIT_FPU_IXC(void) +{ + return (READ_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FPU_IE_5) == (SYSCFG_CFGR1_FPU_IE_5)); +} + +/** + * @brief Configure source input for the EXTI external interrupt. + * @rmtoll SYSCFG_EXTICR1 EXTIx LL_SYSCFG_SetEXTISource\n + * SYSCFG_EXTICR2 EXTIx LL_SYSCFG_SetEXTISource\n + * SYSCFG_EXTICR3 EXTIx LL_SYSCFG_SetEXTISource\n + * SYSCFG_EXTICR4 EXTIx LL_SYSCFG_SetEXTISource + * @param Port This parameter can be one of the following values: + * @arg @ref LL_SYSCFG_EXTI_PORTA + * @arg @ref LL_SYSCFG_EXTI_PORTB + * @arg @ref LL_SYSCFG_EXTI_PORTC + * @arg @ref LL_SYSCFG_EXTI_PORTD + * @arg @ref LL_SYSCFG_EXTI_PORTE + * @arg @ref LL_SYSCFG_EXTI_PORTF (*) + * @arg @ref LL_SYSCFG_EXTI_PORTG (*) + * @arg @ref LL_SYSCFG_EXTI_PORTH + * @arg @ref LL_SYSCFG_EXTI_PORTI (*) + * + * (*) value not defined in all devices + * @param Line This parameter can be one of the following values: + * @arg @ref LL_SYSCFG_EXTI_LINE0 + * @arg @ref LL_SYSCFG_EXTI_LINE1 + * @arg @ref LL_SYSCFG_EXTI_LINE2 + * @arg @ref LL_SYSCFG_EXTI_LINE3 + * @arg @ref LL_SYSCFG_EXTI_LINE4 + * @arg @ref LL_SYSCFG_EXTI_LINE5 + * @arg @ref LL_SYSCFG_EXTI_LINE6 + * @arg @ref LL_SYSCFG_EXTI_LINE7 + * @arg @ref LL_SYSCFG_EXTI_LINE8 + * @arg @ref LL_SYSCFG_EXTI_LINE9 + * @arg @ref LL_SYSCFG_EXTI_LINE10 + * @arg @ref LL_SYSCFG_EXTI_LINE11 + * @arg @ref LL_SYSCFG_EXTI_LINE12 + * @arg @ref LL_SYSCFG_EXTI_LINE13 + * @arg @ref LL_SYSCFG_EXTI_LINE14 + * @arg @ref LL_SYSCFG_EXTI_LINE15 + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_SetEXTISource(uint32_t Port, uint32_t Line) +{ + MODIFY_REG(SYSCFG->EXTICR[Line & 0xFFU], (Line >> 16U), Port << POSITION_VAL((Line >> 16U))); +} + +/** + * @brief Get the configured defined for specific EXTI Line + * @rmtoll SYSCFG_EXTICR1 EXTIx LL_SYSCFG_GetEXTISource\n + * SYSCFG_EXTICR2 EXTIx LL_SYSCFG_GetEXTISource\n + * SYSCFG_EXTICR3 EXTIx LL_SYSCFG_GetEXTISource\n + * SYSCFG_EXTICR4 EXTIx LL_SYSCFG_GetEXTISource + * @param Line This parameter can be one of the following values: + * @arg @ref LL_SYSCFG_EXTI_LINE0 + * @arg @ref LL_SYSCFG_EXTI_LINE1 + * @arg @ref LL_SYSCFG_EXTI_LINE2 + * @arg @ref LL_SYSCFG_EXTI_LINE3 + * @arg @ref LL_SYSCFG_EXTI_LINE4 + * @arg @ref LL_SYSCFG_EXTI_LINE5 + * @arg @ref LL_SYSCFG_EXTI_LINE6 + * @arg @ref LL_SYSCFG_EXTI_LINE7 + * @arg @ref LL_SYSCFG_EXTI_LINE8 + * @arg @ref LL_SYSCFG_EXTI_LINE9 + * @arg @ref LL_SYSCFG_EXTI_LINE10 + * @arg @ref LL_SYSCFG_EXTI_LINE11 + * @arg @ref LL_SYSCFG_EXTI_LINE12 + * @arg @ref LL_SYSCFG_EXTI_LINE13 + * @arg @ref LL_SYSCFG_EXTI_LINE14 + * @arg @ref LL_SYSCFG_EXTI_LINE15 + * @retval Returned value can be one of the following values: + * @arg @ref LL_SYSCFG_EXTI_PORTA + * @arg @ref LL_SYSCFG_EXTI_PORTB + * @arg @ref LL_SYSCFG_EXTI_PORTC + * @arg @ref LL_SYSCFG_EXTI_PORTD + * @arg @ref LL_SYSCFG_EXTI_PORTE + * @arg @ref LL_SYSCFG_EXTI_PORTF (*) + * @arg @ref LL_SYSCFG_EXTI_PORTG (*) + * @arg @ref LL_SYSCFG_EXTI_PORTH + * @arg @ref LL_SYSCFG_EXTI_PORTI (*) + * + * (*) value not defined in all devices + */ +__STATIC_INLINE uint32_t LL_SYSCFG_GetEXTISource(uint32_t Line) +{ + return (uint32_t)(READ_BIT(SYSCFG->EXTICR[Line & 0xFFU], (Line >> 16U)) >> POSITION_VAL(Line >> 16U)); +} + +/** + * @brief Enable SRAM2 Erase (starts a hardware SRAM2 erase operation. This bit is + * automatically cleared at the end of the SRAM2 erase operation.) + * @note This bit is write-protected: setting this bit is possible only after the + * correct key sequence is written in the SYSCFG_SKR register as described in + * the Reference Manual. + * @rmtoll SYSCFG_SCSR SRAM2ER LL_SYSCFG_EnableSRAM2Erase + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableSRAM2Erase(void) +{ + /* Starts a hardware SRAM2 erase operation*/ + SET_BIT(SYSCFG->SCSR, SYSCFG_SCSR_SRAM2ER); +} + +/** + * @brief Check if SRAM2 erase operation is on going + * @rmtoll SYSCFG_SCSR SRAM2BSY LL_SYSCFG_IsSRAM2EraseOngoing + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsSRAM2EraseOngoing(void) +{ + return (READ_BIT(SYSCFG->SCSR, SYSCFG_SCSR_SRAM2BSY) == (SYSCFG_SCSR_SRAM2BSY)); +} + +/** + * @brief Set connections to TIM1/8/15/16/17 Break inputs + * @rmtoll SYSCFG_CFGR2 CLL LL_SYSCFG_SetTIMBreakInputs\n + * SYSCFG_CFGR2 SPL LL_SYSCFG_SetTIMBreakInputs\n + * SYSCFG_CFGR2 PVDL LL_SYSCFG_SetTIMBreakInputs\n + * SYSCFG_CFGR2 ECCL LL_SYSCFG_SetTIMBreakInputs + * @param Break This parameter can be a combination of the following values: + * @arg @ref LL_SYSCFG_TIMBREAK_ECC + * @arg @ref LL_SYSCFG_TIMBREAK_PVD + * @arg @ref LL_SYSCFG_TIMBREAK_SRAM2_PARITY + * @arg @ref LL_SYSCFG_TIMBREAK_LOCKUP + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_SetTIMBreakInputs(uint32_t Break) +{ + MODIFY_REG(SYSCFG->CFGR2, SYSCFG_CFGR2_CLL | SYSCFG_CFGR2_SPL | SYSCFG_CFGR2_PVDL | SYSCFG_CFGR2_ECCL, Break); +} + +/** + * @brief Get connections to TIM1/8/15/16/17 Break inputs + * @rmtoll SYSCFG_CFGR2 CLL LL_SYSCFG_GetTIMBreakInputs\n + * SYSCFG_CFGR2 SPL LL_SYSCFG_GetTIMBreakInputs\n + * SYSCFG_CFGR2 PVDL LL_SYSCFG_GetTIMBreakInputs\n + * SYSCFG_CFGR2 ECCL LL_SYSCFG_GetTIMBreakInputs + * @retval Returned value can be can be a combination of the following values: + * @arg @ref LL_SYSCFG_TIMBREAK_ECC + * @arg @ref LL_SYSCFG_TIMBREAK_PVD + * @arg @ref LL_SYSCFG_TIMBREAK_SRAM2_PARITY + * @arg @ref LL_SYSCFG_TIMBREAK_LOCKUP + */ +__STATIC_INLINE uint32_t LL_SYSCFG_GetTIMBreakInputs(void) +{ + return (uint32_t)(READ_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_CLL | SYSCFG_CFGR2_SPL | SYSCFG_CFGR2_PVDL | SYSCFG_CFGR2_ECCL)); +} + +/** + * @brief Check if SRAM2 parity error detected + * @rmtoll SYSCFG_CFGR2 SPF LL_SYSCFG_IsActiveFlag_SP + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SYSCFG_IsActiveFlag_SP(void) +{ + return (READ_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_SPF) == (SYSCFG_CFGR2_SPF)); +} + +/** + * @brief Clear SRAM2 parity error flag + * @rmtoll SYSCFG_CFGR2 SPF LL_SYSCFG_ClearFlag_SP + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_ClearFlag_SP(void) +{ + SET_BIT(SYSCFG->CFGR2, SYSCFG_CFGR2_SPF); +} + +/** + * @brief Enable SRAM2 page write protection for Pages in range 0 to 31 + * @note Write protection is cleared only by a system reset + * @rmtoll SYSCFG_SWPR PxWP LL_SYSCFG_EnableSRAM2PageWRP_0_31 + * @param SRAM2WRP This parameter can be a combination of the following values: + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE0 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE1 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE2 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE3 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE4 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE5 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE6 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE7 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE8 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE9 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE10 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE11 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE12 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE13 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE14 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE15 + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE16 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE17 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE18 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE19 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE20 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE21 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE22 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE23 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE24 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE25 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE26 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE27 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE28 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE29 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE30 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE31 (*) + * + * (*) value not defined in all devices + * @retval None + */ +/* Legacy define */ +#define LL_SYSCFG_EnableSRAM2PageWRP LL_SYSCFG_EnableSRAM2PageWRP_0_31 +__STATIC_INLINE void LL_SYSCFG_EnableSRAM2PageWRP_0_31(uint32_t SRAM2WRP) +{ + SET_BIT(SYSCFG->SWPR, SRAM2WRP); +} + +#if defined(SYSCFG_SWPR2_PAGE63) +/** + * @brief Enable SRAM2 page write protection for Pages in range 32 to 63 + * @note Write protection is cleared only by a system reset + * @rmtoll SYSCFG_SWPR2 PxWP LL_SYSCFG_EnableSRAM2PageWRP_32_63 + * @param SRAM2WRP This parameter can be a combination of the following values: + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE32 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE33 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE34 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE35 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE36 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE37 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE38 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE39 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE40 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE41 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE42 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE43 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE44 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE45 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE46 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE47 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE48 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE49 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE50 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE51 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE52 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE53 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE54 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE55 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE56 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE57 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE58 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE59 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE60 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE61 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE62 (*) + * @arg @ref LL_SYSCFG_SRAM2WRP_PAGE63 (*) + * + * (*) value not defined in all devices + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_EnableSRAM2PageWRP_32_63(uint32_t SRAM2WRP) +{ + SET_BIT(SYSCFG->SWPR2, SRAM2WRP); +} +#endif /* SYSCFG_SWPR2_PAGE63 */ + +/** + * @brief SRAM2 page write protection lock prior to erase + * @rmtoll SYSCFG_SKR KEY LL_SYSCFG_LockSRAM2WRP + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_LockSRAM2WRP(void) +{ + /* Writing a wrong key reactivates the write protection */ + WRITE_REG(SYSCFG->SKR, 0x00); +} + +/** + * @brief SRAM2 page write protection unlock prior to erase + * @rmtoll SYSCFG_SKR KEY LL_SYSCFG_UnlockSRAM2WRP + * @retval None + */ +__STATIC_INLINE void LL_SYSCFG_UnlockSRAM2WRP(void) +{ + /* unlock the write protection of the SRAM2ER bit */ + WRITE_REG(SYSCFG->SKR, 0xCA); + WRITE_REG(SYSCFG->SKR, 0x53); +} + +/** + * @} + */ + + +/** @defgroup SYSTEM_LL_EF_DBGMCU DBGMCU + * @{ + */ + +/** + * @brief Return the device identifier + * @rmtoll DBGMCU_IDCODE DEV_ID LL_DBGMCU_GetDeviceID + * @retval Values between Min_Data=0x00 and Max_Data=0xFFFF (ex: device ID is 0x6415) + */ +__STATIC_INLINE uint32_t LL_DBGMCU_GetDeviceID(void) +{ + return (uint32_t)(READ_BIT(DBGMCU->IDCODE, DBGMCU_IDCODE_DEV_ID)); +} + +/** + * @brief Return the device revision identifier + * @note This field indicates the revision of the device. + * @rmtoll DBGMCU_IDCODE REV_ID LL_DBGMCU_GetRevisionID + * @retval Values between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_DBGMCU_GetRevisionID(void) +{ + return (uint32_t)(READ_BIT(DBGMCU->IDCODE, DBGMCU_IDCODE_REV_ID) >> DBGMCU_IDCODE_REV_ID_Pos); +} + +/** + * @brief Enable the Debug Module during SLEEP mode + * @rmtoll DBGMCU_CR DBG_SLEEP LL_DBGMCU_EnableDBGSleepMode + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_EnableDBGSleepMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); +} + +/** + * @brief Disable the Debug Module during SLEEP mode + * @rmtoll DBGMCU_CR DBG_SLEEP LL_DBGMCU_DisableDBGSleepMode + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_DisableDBGSleepMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); +} + +/** + * @brief Enable the Debug Module during STOP mode + * @rmtoll DBGMCU_CR DBG_STOP LL_DBGMCU_EnableDBGStopMode + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_EnableDBGStopMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); +} + +/** + * @brief Disable the Debug Module during STOP mode + * @rmtoll DBGMCU_CR DBG_STOP LL_DBGMCU_DisableDBGStopMode + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_DisableDBGStopMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP); +} + +/** + * @brief Enable the Debug Module during STANDBY mode + * @rmtoll DBGMCU_CR DBG_STANDBY LL_DBGMCU_EnableDBGStandbyMode + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_EnableDBGStandbyMode(void) +{ + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); +} + +/** + * @brief Disable the Debug Module during STANDBY mode + * @rmtoll DBGMCU_CR DBG_STANDBY LL_DBGMCU_DisableDBGStandbyMode + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_DisableDBGStandbyMode(void) +{ + CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); +} + +/** + * @brief Set Trace pin assignment control + * @rmtoll DBGMCU_CR TRACE_IOEN LL_DBGMCU_SetTracePinAssignment\n + * DBGMCU_CR TRACE_MODE LL_DBGMCU_SetTracePinAssignment + * @param PinAssignment This parameter can be one of the following values: + * @arg @ref LL_DBGMCU_TRACE_NONE + * @arg @ref LL_DBGMCU_TRACE_ASYNCH + * @arg @ref LL_DBGMCU_TRACE_SYNCH_SIZE1 + * @arg @ref LL_DBGMCU_TRACE_SYNCH_SIZE2 + * @arg @ref LL_DBGMCU_TRACE_SYNCH_SIZE4 + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_SetTracePinAssignment(uint32_t PinAssignment) +{ + MODIFY_REG(DBGMCU->CR, DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE, PinAssignment); +} + +/** + * @brief Get Trace pin assignment control + * @rmtoll DBGMCU_CR TRACE_IOEN LL_DBGMCU_GetTracePinAssignment\n + * DBGMCU_CR TRACE_MODE LL_DBGMCU_GetTracePinAssignment + * @retval Returned value can be one of the following values: + * @arg @ref LL_DBGMCU_TRACE_NONE + * @arg @ref LL_DBGMCU_TRACE_ASYNCH + * @arg @ref LL_DBGMCU_TRACE_SYNCH_SIZE1 + * @arg @ref LL_DBGMCU_TRACE_SYNCH_SIZE2 + * @arg @ref LL_DBGMCU_TRACE_SYNCH_SIZE4 + */ +__STATIC_INLINE uint32_t LL_DBGMCU_GetTracePinAssignment(void) +{ + return (uint32_t)(READ_BIT(DBGMCU->CR, DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE)); +} + +/** + * @brief Freeze APB1 peripherals (group1 peripherals) + * @rmtoll DBGMCU_APB1FZR1 DBG_xxxx_STOP LL_DBGMCU_APB1_GRP1_FreezePeriph + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM2_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM3_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM4_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM5_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM6_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM7_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_RTC_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_WWDG_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_IWDG_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_I2C1_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_I2C2_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_I2C3_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_CAN_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_CAN2_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_LPTIM1_STOP + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_APB1_GRP1_FreezePeriph(uint32_t Periphs) +{ + SET_BIT(DBGMCU->APB1FZR1, Periphs); +} + +/** + * @brief Freeze APB1 peripherals (group2 peripherals) + * @rmtoll DBGMCU_APB1FZR2 DBG_xxxx_STOP LL_DBGMCU_APB1_GRP2_FreezePeriph + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_DBGMCU_APB1_GRP2_I2C4_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP2_LPTIM2_STOP + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_APB1_GRP2_FreezePeriph(uint32_t Periphs) +{ + SET_BIT(DBGMCU->APB1FZR2, Periphs); +} + +/** + * @brief Unfreeze APB1 peripherals (group1 peripherals) + * @rmtoll DBGMCU_APB1FZR1 DBG_xxxx_STOP LL_DBGMCU_APB1_GRP1_UnFreezePeriph + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM2_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM3_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM4_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM5_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM6_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_TIM7_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_RTC_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_WWDG_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_IWDG_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_I2C1_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_I2C2_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_I2C3_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_CAN_STOP + * @arg @ref LL_DBGMCU_APB1_GRP1_CAN2_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP1_LPTIM1_STOP + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_APB1_GRP1_UnFreezePeriph(uint32_t Periphs) +{ + CLEAR_BIT(DBGMCU->APB1FZR1, Periphs); +} + +/** + * @brief Unfreeze APB1 peripherals (group2 peripherals) + * @rmtoll DBGMCU_APB1FZR2 DBG_xxxx_STOP LL_DBGMCU_APB1_GRP2_UnFreezePeriph + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_DBGMCU_APB1_GRP2_I2C4_STOP (*) + * @arg @ref LL_DBGMCU_APB1_GRP2_LPTIM2_STOP + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_APB1_GRP2_UnFreezePeriph(uint32_t Periphs) +{ + CLEAR_BIT(DBGMCU->APB1FZR2, Periphs); +} + +/** + * @brief Freeze APB2 peripherals + * @rmtoll DBGMCU_APB2FZ DBG_TIMx_STOP LL_DBGMCU_APB2_GRP1_FreezePeriph + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM1_STOP + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM8_STOP (*) + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM15_STOP + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM16_STOP + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM17_STOP (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_APB2_GRP1_FreezePeriph(uint32_t Periphs) +{ + SET_BIT(DBGMCU->APB2FZ, Periphs); +} + +/** + * @brief Unfreeze APB2 peripherals + * @rmtoll DBGMCU_APB2FZ DBG_TIMx_STOP LL_DBGMCU_APB2_GRP1_UnFreezePeriph + * @param Periphs This parameter can be a combination of the following values: + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM1_STOP + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM8_STOP (*) + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM15_STOP + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM16_STOP + * @arg @ref LL_DBGMCU_APB2_GRP1_TIM17_STOP (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_DBGMCU_APB2_GRP1_UnFreezePeriph(uint32_t Periphs) +{ + CLEAR_BIT(DBGMCU->APB2FZ, Periphs); +} + +/** + * @} + */ + +#if defined(VREFBUF) +/** @defgroup SYSTEM_LL_EF_VREFBUF VREFBUF + * @{ + */ + +/** + * @brief Enable Internal voltage reference + * @rmtoll VREFBUF_CSR ENVR LL_VREFBUF_Enable + * @retval None + */ +__STATIC_INLINE void LL_VREFBUF_Enable(void) +{ + SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR); +} + +/** + * @brief Disable Internal voltage reference + * @rmtoll VREFBUF_CSR ENVR LL_VREFBUF_Disable + * @retval None + */ +__STATIC_INLINE void LL_VREFBUF_Disable(void) +{ + CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR); +} + +/** + * @brief Enable high impedance (VREF+pin is high impedance) + * @rmtoll VREFBUF_CSR HIZ LL_VREFBUF_EnableHIZ + * @retval None + */ +__STATIC_INLINE void LL_VREFBUF_EnableHIZ(void) +{ + SET_BIT(VREFBUF->CSR, VREFBUF_CSR_HIZ); +} + +/** + * @brief Disable high impedance (VREF+pin is internally connected to the voltage reference buffer output) + * @rmtoll VREFBUF_CSR HIZ LL_VREFBUF_DisableHIZ + * @retval None + */ +__STATIC_INLINE void LL_VREFBUF_DisableHIZ(void) +{ + CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_HIZ); +} + +/** + * @brief Set the Voltage reference scale + * @rmtoll VREFBUF_CSR VRS LL_VREFBUF_SetVoltageScaling + * @param Scale This parameter can be one of the following values: + * @arg @ref LL_VREFBUF_VOLTAGE_SCALE0 + * @arg @ref LL_VREFBUF_VOLTAGE_SCALE1 + * @retval None + */ +__STATIC_INLINE void LL_VREFBUF_SetVoltageScaling(uint32_t Scale) +{ + MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_VRS, Scale); +} + +/** + * @brief Get the Voltage reference scale + * @rmtoll VREFBUF_CSR VRS LL_VREFBUF_GetVoltageScaling + * @retval Returned value can be one of the following values: + * @arg @ref LL_VREFBUF_VOLTAGE_SCALE0 + * @arg @ref LL_VREFBUF_VOLTAGE_SCALE1 + */ +__STATIC_INLINE uint32_t LL_VREFBUF_GetVoltageScaling(void) +{ + return (uint32_t)(READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRS)); +} + +/** + * @brief Check if Voltage reference buffer is ready + * @rmtoll VREFBUF_CSR VRR LL_VREFBUF_IsVREFReady + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_VREFBUF_IsVREFReady(void) +{ + return (READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == (VREFBUF_CSR_VRR)); +} + +/** + * @brief Get the trimming code for VREFBUF calibration + * @rmtoll VREFBUF_CCR TRIM LL_VREFBUF_GetTrimming + * @retval Between 0 and 0x3F + */ +__STATIC_INLINE uint32_t LL_VREFBUF_GetTrimming(void) +{ + return (uint32_t)(READ_BIT(VREFBUF->CCR, VREFBUF_CCR_TRIM)); +} + +/** + * @brief Set the trimming code for VREFBUF calibration (Tune the internal reference buffer voltage) + * @rmtoll VREFBUF_CCR TRIM LL_VREFBUF_SetTrimming + * @param Value Between 0 and 0x3F + * @retval None + */ +__STATIC_INLINE void LL_VREFBUF_SetTrimming(uint32_t Value) +{ + WRITE_REG(VREFBUF->CCR, Value); +} + +/** + * @} + */ +#endif /* VREFBUF */ + +/** @defgroup SYSTEM_LL_EF_FLASH FLASH + * @{ + */ + +/** + * @brief Set FLASH Latency + * @rmtoll FLASH_ACR LATENCY LL_FLASH_SetLatency + * @param Latency This parameter can be one of the following values: + * @arg @ref LL_FLASH_LATENCY_0 + * @arg @ref LL_FLASH_LATENCY_1 + * @arg @ref LL_FLASH_LATENCY_2 + * @arg @ref LL_FLASH_LATENCY_3 + * @arg @ref LL_FLASH_LATENCY_4 + * @arg @ref LL_FLASH_LATENCY_5 (*) + * @arg @ref LL_FLASH_LATENCY_6 (*) + * @arg @ref LL_FLASH_LATENCY_7 (*) + * @arg @ref LL_FLASH_LATENCY_8 (*) + * @arg @ref LL_FLASH_LATENCY_9 (*) + * @arg @ref LL_FLASH_LATENCY_10 (*) + * @arg @ref LL_FLASH_LATENCY_11 (*) + * @arg @ref LL_FLASH_LATENCY_12 (*) + * @arg @ref LL_FLASH_LATENCY_13 (*) + * @arg @ref LL_FLASH_LATENCY_14 (*) + * @arg @ref LL_FLASH_LATENCY_15 (*) + * + * (*) value not defined in all devices. + * @retval None + */ +__STATIC_INLINE void LL_FLASH_SetLatency(uint32_t Latency) +{ + MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, Latency); +} + +/** + * @brief Get FLASH Latency + * @rmtoll FLASH_ACR LATENCY LL_FLASH_GetLatency + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_LATENCY_0 + * @arg @ref LL_FLASH_LATENCY_1 + * @arg @ref LL_FLASH_LATENCY_2 + * @arg @ref LL_FLASH_LATENCY_3 + * @arg @ref LL_FLASH_LATENCY_4 + * @arg @ref LL_FLASH_LATENCY_5 (*) + * @arg @ref LL_FLASH_LATENCY_6 (*) + * @arg @ref LL_FLASH_LATENCY_7 (*) + * @arg @ref LL_FLASH_LATENCY_8 (*) + * @arg @ref LL_FLASH_LATENCY_9 (*) + * @arg @ref LL_FLASH_LATENCY_10 (*) + * @arg @ref LL_FLASH_LATENCY_11 (*) + * @arg @ref LL_FLASH_LATENCY_12 (*) + * @arg @ref LL_FLASH_LATENCY_13 (*) + * @arg @ref LL_FLASH_LATENCY_14 (*) + * @arg @ref LL_FLASH_LATENCY_15 (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_FLASH_GetLatency(void) +{ + return (uint32_t)(READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY)); +} + +/** + * @brief Enable Prefetch + * @rmtoll FLASH_ACR PRFTEN LL_FLASH_EnablePrefetch + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnablePrefetch(void) +{ + SET_BIT(FLASH->ACR, FLASH_ACR_PRFTEN); +} + +/** + * @brief Disable Prefetch + * @rmtoll FLASH_ACR PRFTEN LL_FLASH_DisablePrefetch + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisablePrefetch(void) +{ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_PRFTEN); +} + +/** + * @brief Check if Prefetch buffer is enabled + * @rmtoll FLASH_ACR PRFTEN LL_FLASH_IsPrefetchEnabled + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FLASH_IsPrefetchEnabled(void) +{ + return (READ_BIT(FLASH->ACR, FLASH_ACR_PRFTEN) == (FLASH_ACR_PRFTEN)); +} + +/** + * @brief Enable Instruction cache + * @rmtoll FLASH_ACR ICEN LL_FLASH_EnableInstCache + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnableInstCache(void) +{ + SET_BIT(FLASH->ACR, FLASH_ACR_ICEN); +} + +/** + * @brief Disable Instruction cache + * @rmtoll FLASH_ACR ICEN LL_FLASH_DisableInstCache + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisableInstCache(void) +{ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICEN); +} + +/** + * @brief Enable Data cache + * @rmtoll FLASH_ACR DCEN LL_FLASH_EnableDataCache + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnableDataCache(void) +{ + SET_BIT(FLASH->ACR, FLASH_ACR_DCEN); +} + +/** + * @brief Disable Data cache + * @rmtoll FLASH_ACR DCEN LL_FLASH_DisableDataCache + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisableDataCache(void) +{ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCEN); +} + +/** + * @brief Enable Instruction cache reset + * @note bit can be written only when the instruction cache is disabled + * @rmtoll FLASH_ACR ICRST LL_FLASH_EnableInstCacheReset + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnableInstCacheReset(void) +{ + SET_BIT(FLASH->ACR, FLASH_ACR_ICRST); +} + +/** + * @brief Disable Instruction cache reset + * @rmtoll FLASH_ACR ICRST LL_FLASH_DisableInstCacheReset + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisableInstCacheReset(void) +{ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_ICRST); +} + +/** + * @brief Enable Data cache reset + * @note bit can be written only when the data cache is disabled + * @rmtoll FLASH_ACR DCRST LL_FLASH_EnableDataCacheReset + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnableDataCacheReset(void) +{ + SET_BIT(FLASH->ACR, FLASH_ACR_DCRST); +} + +/** + * @brief Disable Data cache reset + * @rmtoll FLASH_ACR DCRST LL_FLASH_DisableDataCacheReset + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisableDataCacheReset(void) +{ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_DCRST); +} + +/** + * @brief Enable Flash Power-down mode during run mode or Low-power run mode + * @note Flash memory can be put in power-down mode only when the code is executed + * from RAM + * @note Flash must not be accessed when power down is enabled + * @note Flash must not be put in power-down while a program or an erase operation + * is on-going + * @rmtoll FLASH_ACR RUN_PD LL_FLASH_EnableRunPowerDown\n + * FLASH_PDKEYR PDKEY1 LL_FLASH_EnableRunPowerDown\n + * FLASH_PDKEYR PDKEY2 LL_FLASH_EnableRunPowerDown + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnableRunPowerDown(void) +{ + /* Following values must be written consecutively to unlock the RUN_PD bit in + FLASH_ACR */ + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); + SET_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); +} + +/** + * @brief Disable Flash Power-down mode during run mode or Low-power run mode + * @rmtoll FLASH_ACR RUN_PD LL_FLASH_DisableRunPowerDown\n + * FLASH_PDKEYR PDKEY1 LL_FLASH_DisableRunPowerDown\n + * FLASH_PDKEYR PDKEY2 LL_FLASH_DisableRunPowerDown + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisableRunPowerDown(void) +{ + /* Following values must be written consecutively to unlock the RUN_PD bit in + FLASH_ACR */ + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY1); + WRITE_REG(FLASH->PDKEYR, FLASH_PDKEY2); + CLEAR_BIT(FLASH->ACR, FLASH_ACR_RUN_PD); +} + +/** + * @brief Enable Flash Power-down mode during Sleep or Low-power sleep mode + * @note Flash must not be put in power-down while a program or an erase operation + * is on-going + * @rmtoll FLASH_ACR SLEEP_PD LL_FLASH_EnableSleepPowerDown + * @retval None + */ +__STATIC_INLINE void LL_FLASH_EnableSleepPowerDown(void) +{ + SET_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD); +} + +/** + * @brief Disable Flash Power-down mode during Sleep or Low-power sleep mode + * @rmtoll FLASH_ACR SLEEP_PD LL_FLASH_DisableSleepPowerDown + * @retval None + */ +__STATIC_INLINE void LL_FLASH_DisableSleepPowerDown(void) +{ + CLEAR_BIT(FLASH->ACR, FLASH_ACR_SLEEP_PD); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (FLASH) || defined (SYSCFG) || defined (DBGMCU) || defined (VREFBUF) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_SYSTEM_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_tim.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_tim.h new file mode 100644 index 0000000..fb8110f --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_tim.h @@ -0,0 +1,5084 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_tim.h + * @author MCD Application Team + * @brief Header file of TIM 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 __STM32L4xx_LL_TIM_H +#define __STM32L4xx_LL_TIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (TIM1) || defined (TIM8) || defined (TIM2) || defined (TIM3) || defined (TIM4) || defined (TIM5) || defined (TIM15) || defined (TIM16) || defined (TIM17) || defined (TIM6) || defined (TIM7) + +/** @defgroup TIM_LL TIM + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup TIM_LL_Private_Variables TIM Private Variables + * @{ + */ +static const uint8_t OFFSET_TAB_CCMRx[] = +{ + 0x00U, /* 0: TIMx_CH1 */ + 0x00U, /* 1: TIMx_CH1N */ + 0x00U, /* 2: TIMx_CH2 */ + 0x00U, /* 3: TIMx_CH2N */ + 0x04U, /* 4: TIMx_CH3 */ + 0x04U, /* 5: TIMx_CH3N */ + 0x04U, /* 6: TIMx_CH4 */ + 0x3CU, /* 7: TIMx_CH5 */ + 0x3CU /* 8: TIMx_CH6 */ +}; + +static const uint8_t SHIFT_TAB_OCxx[] = +{ + 0U, /* 0: OC1M, OC1FE, OC1PE */ + 0U, /* 1: - NA */ + 8U, /* 2: OC2M, OC2FE, OC2PE */ + 0U, /* 3: - NA */ + 0U, /* 4: OC3M, OC3FE, OC3PE */ + 0U, /* 5: - NA */ + 8U, /* 6: OC4M, OC4FE, OC4PE */ + 0U, /* 7: OC5M, OC5FE, OC5PE */ + 8U /* 8: OC6M, OC6FE, OC6PE */ +}; + +static const uint8_t SHIFT_TAB_ICxx[] = +{ + 0U, /* 0: CC1S, IC1PSC, IC1F */ + 0U, /* 1: - NA */ + 8U, /* 2: CC2S, IC2PSC, IC2F */ + 0U, /* 3: - NA */ + 0U, /* 4: CC3S, IC3PSC, IC3F */ + 0U, /* 5: - NA */ + 8U, /* 6: CC4S, IC4PSC, IC4F */ + 0U, /* 7: - NA */ + 0U /* 8: - NA */ +}; + +static const uint8_t SHIFT_TAB_CCxP[] = +{ + 0U, /* 0: CC1P */ + 2U, /* 1: CC1NP */ + 4U, /* 2: CC2P */ + 6U, /* 3: CC2NP */ + 8U, /* 4: CC3P */ + 10U, /* 5: CC3NP */ + 12U, /* 6: CC4P */ + 16U, /* 7: CC5P */ + 20U /* 8: CC6P */ +}; + +static const uint8_t SHIFT_TAB_OISx[] = +{ + 0U, /* 0: OIS1 */ + 1U, /* 1: OIS1N */ + 2U, /* 2: OIS2 */ + 3U, /* 3: OIS2N */ + 4U, /* 4: OIS3 */ + 5U, /* 5: OIS3N */ + 6U, /* 6: OIS4 */ + 8U, /* 7: OIS5 */ + 10U /* 8: OIS6 */ +}; +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup TIM_LL_Private_Constants TIM Private Constants + * @{ + */ + +/* Defines used for the bit position in the register and perform offsets */ +#define TIM_POSITION_BRK_SOURCE (POSITION_VAL(Source) & 0x1FUL) + +/* Generic bit definitions for TIMx_OR2 register */ +#define TIMx_OR2_BKINP TIM1_OR2_BKINP /*!< BRK BKIN input polarity */ +#define TIMx_OR2_ETRSEL TIM1_OR2_ETRSEL /*!< TIMx ETR source selection */ + +/* Remap mask definitions */ +#define TIMx_OR1_RMP_SHIFT 16U +#define TIMx_OR1_RMP_MASK 0x0000FFFFU +#if defined(ADC3) +#define TIM1_OR1_RMP_MASK ((TIM1_OR1_ETR_ADC1_RMP | TIM1_OR1_ETR_ADC3_RMP | TIM1_OR1_TI1_RMP) << TIMx_OR1_RMP_SHIFT) +#else +#define TIM1_OR1_RMP_MASK ((TIM1_OR1_ETR_ADC1_RMP | TIM1_OR1_TI1_RMP) << TIMx_OR1_RMP_SHIFT) +#endif /* ADC3 */ +#define TIM2_OR1_RMP_MASK ((TIM2_OR1_TI4_RMP | TIM2_OR1_ETR1_RMP | TIM2_OR1_ITR1_RMP) << TIMx_OR1_RMP_SHIFT) +#define TIM3_OR1_RMP_MASK (TIM3_OR1_TI1_RMP << TIMx_OR1_RMP_SHIFT) +#if defined(ADC2) && defined(ADC3) +#define TIM8_OR1_RMP_MASK ((TIM8_OR1_ETR_ADC2_RMP | TIM8_OR1_ETR_ADC3_RMP | TIM8_OR1_TI1_RMP) << TIMx_OR1_RMP_SHIFT) +#else +#define TIM8_OR1_RMP_MASK (TIM8_OR1_TI1_RMP << TIMx_OR1_RMP_SHIFT) +#endif /* ADC2 & ADC3 */ +#define TIM15_OR1_RMP_MASK (TIM15_OR1_TI1_RMP << TIMx_OR1_RMP_SHIFT) +#define TIM16_OR1_RMP_MASK (TIM16_OR1_TI1_RMP << TIMx_OR1_RMP_SHIFT) +#define TIM17_OR1_RMP_MASK (TIM17_OR1_TI1_RMP << TIMx_OR1_RMP_SHIFT) + +/* Mask used to set the TDG[x:0] of the DTG bits of the TIMx_BDTR register */ +#define DT_DELAY_1 ((uint8_t)0x7F) +#define DT_DELAY_2 ((uint8_t)0x3F) +#define DT_DELAY_3 ((uint8_t)0x1F) +#define DT_DELAY_4 ((uint8_t)0x1F) + +/* Mask used to set the DTG[7:5] bits of the DTG bits of the TIMx_BDTR register */ +#define DT_RANGE_1 ((uint8_t)0x00) +#define DT_RANGE_2 ((uint8_t)0x80) +#define DT_RANGE_3 ((uint8_t)0xC0) +#define DT_RANGE_4 ((uint8_t)0xE0) + +/** Legacy definitions for compatibility purpose +@cond 0 + */ +#if defined(DFSDM1_Channel0) +#define TIMx_OR2_BKDFBK0E TIMx_OR2_BKDF1BK0E +#define TIMx_OR3_BK2DFBK1E TIMx_OR3_BK2DF1BK1E +#endif /* DFSDM1_Channel0 */ +/** +@endcond + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup TIM_LL_Private_Macros TIM Private Macros + * @{ + */ +/** @brief Convert channel id into channel index. + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_TIM_CHANNEL_CH1 + * @arg @ref LL_TIM_CHANNEL_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval none + */ +#define TIM_GET_CHANNEL_INDEX( __CHANNEL__) \ + (((__CHANNEL__) == LL_TIM_CHANNEL_CH1) ? 0U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH1N) ? 1U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH2) ? 2U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH2N) ? 3U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH3) ? 4U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH3N) ? 5U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH4) ? 6U :\ + ((__CHANNEL__) == LL_TIM_CHANNEL_CH5) ? 7U : 8U) + +/** @brief Calculate the deadtime sampling period(in ps). + * @param __TIMCLK__ timer input clock frequency (in Hz). + * @param __CKD__ This parameter can be one of the following values: + * @arg @ref LL_TIM_CLOCKDIVISION_DIV1 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV2 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV4 + * @retval none + */ +#define TIM_CALC_DTS(__TIMCLK__, __CKD__) \ + (((__CKD__) == LL_TIM_CLOCKDIVISION_DIV1) ? ((uint64_t)1000000000000U/(__TIMCLK__)) : \ + ((__CKD__) == LL_TIM_CLOCKDIVISION_DIV2) ? ((uint64_t)1000000000000U/((__TIMCLK__) >> 1U)) : \ + ((uint64_t)1000000000000U/((__TIMCLK__) >> 2U))) +/** + * @} + */ + + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup TIM_LL_ES_INIT TIM Exported Init structure + * @{ + */ + +/** + * @brief TIM Time Base configuration structure definition. + */ +typedef struct +{ + uint16_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between Min_Data=0x0000 and Max_Data=0xFFFF. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetPrescaler().*/ + + uint32_t CounterMode; /*!< Specifies the counter mode. + This parameter can be a value of @ref TIM_LL_EC_COUNTERMODE. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetCounterMode().*/ + + uint32_t Autoreload; /*!< Specifies the auto reload value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter must be a number between Min_Data=0x0000 and Max_Data=0xFFFF. + Some timer instances may support 32 bits counters. In that case this parameter must + be a number between 0x0000 and 0xFFFFFFFF. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetAutoReload().*/ + + uint32_t ClockDivision; /*!< Specifies the clock division. + This parameter can be a value of @ref TIM_LL_EC_CLOCKDIVISION. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetClockDivision().*/ + + uint32_t RepetitionCounter; /*!< Specifies the repetition counter value. Each time the RCR downcounter + reaches zero, an update event is generated and counting restarts + from the RCR value (N). + This means in PWM mode that (N+1) corresponds to: + - the number of PWM periods in edge-aligned mode + - the number of half PWM period in center-aligned mode + GP timers: this parameter must be a number between Min_Data = 0x00 and + Max_Data = 0xFF. + Advanced timers: this parameter must be a number between Min_Data = 0x0000 and + Max_Data = 0xFFFF. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetRepetitionCounter().*/ +} LL_TIM_InitTypeDef; + +/** + * @brief TIM Output Compare configuration structure definition. + */ +typedef struct +{ + uint32_t OCMode; /*!< Specifies the output mode. + This parameter can be a value of @ref TIM_LL_EC_OCMODE. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetMode().*/ + + uint32_t OCState; /*!< Specifies the TIM Output Compare state. + This parameter can be a value of @ref TIM_LL_EC_OCSTATE. + + This feature can be modified afterwards using unitary functions + @ref LL_TIM_CC_EnableChannel() or @ref LL_TIM_CC_DisableChannel().*/ + + uint32_t OCNState; /*!< Specifies the TIM complementary Output Compare state. + This parameter can be a value of @ref TIM_LL_EC_OCSTATE. + + This feature can be modified afterwards using unitary functions + @ref LL_TIM_CC_EnableChannel() or @ref LL_TIM_CC_DisableChannel().*/ + + uint32_t CompareValue; /*!< Specifies the Compare value to be loaded into the Capture Compare Register. + This parameter can be a number between Min_Data=0x0000 and Max_Data=0xFFFF. + + This feature can be modified afterwards using unitary function + LL_TIM_OC_SetCompareCHx (x=1..6).*/ + + uint32_t OCPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_LL_EC_OCPOLARITY. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetPolarity().*/ + + uint32_t OCNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_LL_EC_OCPOLARITY. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetPolarity().*/ + + + uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_LL_EC_OCIDLESTATE. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetIdleState().*/ + + uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_LL_EC_OCIDLESTATE. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetIdleState().*/ +} LL_TIM_OC_InitTypeDef; + +/** + * @brief TIM Input Capture configuration structure definition. + */ + +typedef struct +{ + + uint32_t ICPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ + + uint32_t ICActiveInput; /*!< Specifies the input. + This parameter can be a value of @ref TIM_LL_EC_ACTIVEINPUT. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetActiveInput().*/ + + uint32_t ICPrescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_LL_EC_ICPSC. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ + + uint32_t ICFilter; /*!< Specifies the input capture filter. + This parameter can be a value of @ref TIM_LL_EC_IC_FILTER. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ +} LL_TIM_IC_InitTypeDef; + + +/** + * @brief TIM Encoder interface configuration structure definition. + */ +typedef struct +{ + uint32_t EncoderMode; /*!< Specifies the encoder resolution (x2 or x4). + This parameter can be a value of @ref TIM_LL_EC_ENCODERMODE. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetEncoderMode().*/ + + uint32_t IC1Polarity; /*!< Specifies the active edge of TI1 input. + This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ + + uint32_t IC1ActiveInput; /*!< Specifies the TI1 input source + This parameter can be a value of @ref TIM_LL_EC_ACTIVEINPUT. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetActiveInput().*/ + + uint32_t IC1Prescaler; /*!< Specifies the TI1 input prescaler value. + This parameter can be a value of @ref TIM_LL_EC_ICPSC. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ + + uint32_t IC1Filter; /*!< Specifies the TI1 input filter. + This parameter can be a value of @ref TIM_LL_EC_IC_FILTER. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ + + uint32_t IC2Polarity; /*!< Specifies the active edge of TI2 input. + This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ + + uint32_t IC2ActiveInput; /*!< Specifies the TI2 input source + This parameter can be a value of @ref TIM_LL_EC_ACTIVEINPUT. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetActiveInput().*/ + + uint32_t IC2Prescaler; /*!< Specifies the TI2 input prescaler value. + This parameter can be a value of @ref TIM_LL_EC_ICPSC. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ + + uint32_t IC2Filter; /*!< Specifies the TI2 input filter. + This parameter can be a value of @ref TIM_LL_EC_IC_FILTER. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ + +} LL_TIM_ENCODER_InitTypeDef; + +/** + * @brief TIM Hall sensor interface configuration structure definition. + */ +typedef struct +{ + + uint32_t IC1Polarity; /*!< Specifies the active edge of TI1 input. + This parameter can be a value of @ref TIM_LL_EC_IC_POLARITY. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPolarity().*/ + + uint32_t IC1Prescaler; /*!< Specifies the TI1 input prescaler value. + Prescaler must be set to get a maximum counter period longer than the + time interval between 2 consecutive changes on the Hall inputs. + This parameter can be a value of @ref TIM_LL_EC_ICPSC. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetPrescaler().*/ + + uint32_t IC1Filter; /*!< Specifies the TI1 input filter. + This parameter can be a value of + @ref TIM_LL_EC_IC_FILTER. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_IC_SetFilter().*/ + + uint32_t CommutationDelay; /*!< Specifies the compare value to be loaded into the Capture Compare Register. + A positive pulse (TRGO event) is generated with a programmable delay every time + a change occurs on the Hall inputs. + This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetCompareCH2().*/ +} LL_TIM_HALLSENSOR_InitTypeDef; + +/** + * @brief BDTR (Break and Dead Time) structure definition + */ +typedef struct +{ + uint32_t OSSRState; /*!< Specifies the Off-State selection used in Run mode. + This parameter can be a value of @ref TIM_LL_EC_OSSR + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetOffStates() + + @note This bit-field cannot be modified as long as LOCK level 2 has been + programmed. */ + + uint32_t OSSIState; /*!< Specifies the Off-State used in Idle state. + This parameter can be a value of @ref TIM_LL_EC_OSSI + + This feature can be modified afterwards using unitary function + @ref LL_TIM_SetOffStates() + + @note This bit-field cannot be modified as long as LOCK level 2 has been + programmed. */ + + uint32_t LockLevel; /*!< Specifies the LOCK level parameters. + This parameter can be a value of @ref TIM_LL_EC_LOCKLEVEL + + @note The LOCK bits can be written only once after the reset. Once the TIMx_BDTR + register has been written, their content is frozen until the next reset.*/ + + uint8_t DeadTime; /*!< Specifies the delay time between the switching-off and the + switching-on of the outputs. + This parameter can be a number between Min_Data = 0x00 and Max_Data = 0xFF. + + This feature can be modified afterwards using unitary function + @ref LL_TIM_OC_SetDeadTime() + + @note This bit-field can not be modified as long as LOCK level 1, 2 or 3 has been + programmed. */ + + uint16_t BreakState; /*!< Specifies whether the TIM Break input is enabled or not. + This parameter can be a value of @ref TIM_LL_EC_BREAK_ENABLE + + This feature can be modified afterwards using unitary functions + @ref LL_TIM_EnableBRK() or @ref LL_TIM_DisableBRK() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ + + uint32_t BreakPolarity; /*!< Specifies the TIM Break Input pin polarity. + This parameter can be a value of @ref TIM_LL_EC_BREAK_POLARITY + + This feature can be modified afterwards using unitary function + @ref LL_TIM_ConfigBRK() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ + + uint32_t BreakFilter; /*!< Specifies the TIM Break Filter. + This parameter can be a value of @ref TIM_LL_EC_BREAK_FILTER + + This feature can be modified afterwards using unitary function + @ref LL_TIM_ConfigBRK() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ + + uint32_t Break2State; /*!< Specifies whether the TIM Break2 input is enabled or not. + This parameter can be a value of @ref TIM_LL_EC_BREAK2_ENABLE + + This feature can be modified afterwards using unitary functions + @ref LL_TIM_EnableBRK2() or @ref LL_TIM_DisableBRK2() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ + + uint32_t Break2Polarity; /*!< Specifies the TIM Break2 Input pin polarity. + This parameter can be a value of @ref TIM_LL_EC_BREAK2_POLARITY + + This feature can be modified afterwards using unitary function + @ref LL_TIM_ConfigBRK2() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ + + uint32_t Break2Filter; /*!< Specifies the TIM Break2 Filter. + This parameter can be a value of @ref TIM_LL_EC_BREAK2_FILTER + + This feature can be modified afterwards using unitary function + @ref LL_TIM_ConfigBRK2() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ + + uint32_t AutomaticOutput; /*!< Specifies whether the TIM Automatic Output feature is enabled or not. + This parameter can be a value of @ref TIM_LL_EC_AUTOMATICOUTPUT_ENABLE + + This feature can be modified afterwards using unitary functions + @ref LL_TIM_EnableAutomaticOutput() or @ref LL_TIM_DisableAutomaticOutput() + + @note This bit-field can not be modified as long as LOCK level 1 has been + programmed. */ +} LL_TIM_BDTR_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup TIM_LL_Exported_Constants TIM Exported Constants + * @{ + */ + +/** @defgroup TIM_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_TIM_ReadReg function. + * @{ + */ +#define LL_TIM_SR_UIF TIM_SR_UIF /*!< Update interrupt flag */ +#define LL_TIM_SR_CC1IF TIM_SR_CC1IF /*!< Capture/compare 1 interrupt flag */ +#define LL_TIM_SR_CC2IF TIM_SR_CC2IF /*!< Capture/compare 2 interrupt flag */ +#define LL_TIM_SR_CC3IF TIM_SR_CC3IF /*!< Capture/compare 3 interrupt flag */ +#define LL_TIM_SR_CC4IF TIM_SR_CC4IF /*!< Capture/compare 4 interrupt flag */ +#define LL_TIM_SR_CC5IF TIM_SR_CC5IF /*!< Capture/compare 5 interrupt flag */ +#define LL_TIM_SR_CC6IF TIM_SR_CC6IF /*!< Capture/compare 6 interrupt flag */ +#define LL_TIM_SR_COMIF TIM_SR_COMIF /*!< COM interrupt flag */ +#define LL_TIM_SR_TIF TIM_SR_TIF /*!< Trigger interrupt flag */ +#define LL_TIM_SR_BIF TIM_SR_BIF /*!< Break interrupt flag */ +#define LL_TIM_SR_B2IF TIM_SR_B2IF /*!< Second break interrupt flag */ +#define LL_TIM_SR_CC1OF TIM_SR_CC1OF /*!< Capture/Compare 1 overcapture flag */ +#define LL_TIM_SR_CC2OF TIM_SR_CC2OF /*!< Capture/Compare 2 overcapture flag */ +#define LL_TIM_SR_CC3OF TIM_SR_CC3OF /*!< Capture/Compare 3 overcapture flag */ +#define LL_TIM_SR_CC4OF TIM_SR_CC4OF /*!< Capture/Compare 4 overcapture flag */ +#define LL_TIM_SR_SBIF TIM_SR_SBIF /*!< System Break interrupt flag */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup TIM_LL_EC_BREAK_ENABLE Break Enable + * @{ + */ +#define LL_TIM_BREAK_DISABLE 0x00000000U /*!< Break function disabled */ +#define LL_TIM_BREAK_ENABLE TIM_BDTR_BKE /*!< Break function enabled */ +/** + * @} + */ + +/** @defgroup TIM_LL_EC_BREAK2_ENABLE Break2 Enable + * @{ + */ +#define LL_TIM_BREAK2_DISABLE 0x00000000U /*!< Break2 function disabled */ +#define LL_TIM_BREAK2_ENABLE TIM_BDTR_BK2E /*!< Break2 function enabled */ +/** + * @} + */ + +/** @defgroup TIM_LL_EC_AUTOMATICOUTPUT_ENABLE Automatic output enable + * @{ + */ +#define LL_TIM_AUTOMATICOUTPUT_DISABLE 0x00000000U /*!< MOE can be set only by software */ +#define LL_TIM_AUTOMATICOUTPUT_ENABLE TIM_BDTR_AOE /*!< MOE can be set by software or automatically at the next update event */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup TIM_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_TIM_ReadReg and LL_TIM_WriteReg functions. + * @{ + */ +#define LL_TIM_DIER_UIE TIM_DIER_UIE /*!< Update interrupt enable */ +#define LL_TIM_DIER_CC1IE TIM_DIER_CC1IE /*!< Capture/compare 1 interrupt enable */ +#define LL_TIM_DIER_CC2IE TIM_DIER_CC2IE /*!< Capture/compare 2 interrupt enable */ +#define LL_TIM_DIER_CC3IE TIM_DIER_CC3IE /*!< Capture/compare 3 interrupt enable */ +#define LL_TIM_DIER_CC4IE TIM_DIER_CC4IE /*!< Capture/compare 4 interrupt enable */ +#define LL_TIM_DIER_COMIE TIM_DIER_COMIE /*!< COM interrupt enable */ +#define LL_TIM_DIER_TIE TIM_DIER_TIE /*!< Trigger interrupt enable */ +#define LL_TIM_DIER_BIE TIM_DIER_BIE /*!< Break interrupt enable */ +/** + * @} + */ + +/** @defgroup TIM_LL_EC_UPDATESOURCE Update Source + * @{ + */ +#define LL_TIM_UPDATESOURCE_REGULAR 0x00000000U /*!< Counter overflow/underflow, Setting the UG bit or Update generation through the slave mode controller generates an update request */ +#define LL_TIM_UPDATESOURCE_COUNTER TIM_CR1_URS /*!< Only counter overflow/underflow generates an update request */ +/** + * @} + */ + +/** @defgroup TIM_LL_EC_ONEPULSEMODE One Pulse Mode + * @{ + */ +#define LL_TIM_ONEPULSEMODE_SINGLE TIM_CR1_OPM /*!< Counter stops counting at the next update event */ +#define LL_TIM_ONEPULSEMODE_REPETITIVE 0x00000000U /*!< Counter is not stopped at update event */ +/** + * @} + */ + +/** @defgroup TIM_LL_EC_COUNTERMODE Counter Mode + * @{ + */ +#define LL_TIM_COUNTERMODE_UP 0x00000000U /*!TIMx_CCRy else active.*/ +#define LL_TIM_OCMODE_PWM2 (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0) /*!TIMx_CCRy else inactive*/ +#define LL_TIM_OCMODE_RETRIG_OPM1 TIM_CCMR1_OC1M_3 /*!__REG__, (__VALUE__)) + +/** + * @brief Read a value in TIM register. + * @param __INSTANCE__ TIM Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_TIM_ReadReg(__INSTANCE__, __REG__) READ_REG((__INSTANCE__)->__REG__) +/** + * @} + */ + +/** + * @brief HELPER macro retrieving the UIFCPY flag from the counter value. + * @note ex: @ref __LL_TIM_GETFLAG_UIFCPY (@ref LL_TIM_GetCounter ()); + * @note Relevant only if UIF flag remapping has been enabled (UIF status bit is copied + * to TIMx_CNT register bit 31) + * @param __CNT__ Counter value + * @retval UIF status bit + */ +#define __LL_TIM_GETFLAG_UIFCPY(__CNT__) \ + (READ_BIT((__CNT__), TIM_CNT_UIFCPY) >> TIM_CNT_UIFCPY_Pos) + +/** + * @brief HELPER macro calculating DTG[0:7] in the TIMx_BDTR register to achieve the requested dead time duration. + * @note ex: @ref __LL_TIM_CALC_DEADTIME (80000000, @ref LL_TIM_GetClockDivision (), 120); + * @param __TIMCLK__ timer input clock frequency (in Hz) + * @param __CKD__ This parameter can be one of the following values: + * @arg @ref LL_TIM_CLOCKDIVISION_DIV1 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV2 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV4 + * @param __DT__ deadtime duration (in ns) + * @retval DTG[0:7] + */ +#define __LL_TIM_CALC_DEADTIME(__TIMCLK__, __CKD__, __DT__) \ + ( (((uint64_t)((__DT__)*1000U)) < ((DT_DELAY_1+1U) * TIM_CALC_DTS((__TIMCLK__), (__CKD__)))) ? \ + (uint8_t)(((uint64_t)((__DT__)*1000U) / TIM_CALC_DTS((__TIMCLK__), (__CKD__))) & DT_DELAY_1) : \ + (((uint64_t)((__DT__)*1000U)) < ((64U + (DT_DELAY_2+1U)) * 2U * TIM_CALC_DTS((__TIMCLK__), (__CKD__)))) ? \ + (uint8_t)(DT_RANGE_2 | ((uint8_t)((uint8_t)((((uint64_t)((__DT__)*1000U))/ TIM_CALC_DTS((__TIMCLK__), \ + (__CKD__))) >> 1U) - (uint8_t) 64) & DT_DELAY_2)) :\ + (((uint64_t)((__DT__)*1000U)) < ((32U + (DT_DELAY_3+1U)) * 8U * TIM_CALC_DTS((__TIMCLK__), (__CKD__)))) ? \ + (uint8_t)(DT_RANGE_3 | ((uint8_t)((uint8_t)(((((uint64_t)(__DT__)*1000U))/ TIM_CALC_DTS((__TIMCLK__), \ + (__CKD__))) >> 3U) - (uint8_t) 32) & DT_DELAY_3)) :\ + (((uint64_t)((__DT__)*1000U)) < ((32U + (DT_DELAY_4+1U)) * 16U * TIM_CALC_DTS((__TIMCLK__), (__CKD__)))) ? \ + (uint8_t)(DT_RANGE_4 | ((uint8_t)((uint8_t)(((((uint64_t)(__DT__)*1000U))/ TIM_CALC_DTS((__TIMCLK__), \ + (__CKD__))) >> 4U) - (uint8_t) 32) & DT_DELAY_4)) :\ + 0U) + +/** + * @brief HELPER macro calculating the prescaler value to achieve the required counter clock frequency. + * @note ex: @ref __LL_TIM_CALC_PSC (80000000, 1000000); + * @param __TIMCLK__ timer input clock frequency (in Hz) + * @param __CNTCLK__ counter clock frequency (in Hz) + * @retval Prescaler value (between Min_Data=0 and Max_Data=65535) + */ +#define __LL_TIM_CALC_PSC(__TIMCLK__, __CNTCLK__) \ + (((__TIMCLK__) >= (__CNTCLK__)) ? (uint32_t)((((__TIMCLK__) + (__CNTCLK__)/2U)/(__CNTCLK__)) - 1U) : 0U) + +/** + * @brief HELPER macro calculating the auto-reload value to achieve the required output signal frequency. + * @note ex: @ref __LL_TIM_CALC_ARR (1000000, @ref LL_TIM_GetPrescaler (), 10000); + * @param __TIMCLK__ timer input clock frequency (in Hz) + * @param __PSC__ prescaler + * @param __FREQ__ output signal frequency (in Hz) + * @retval Auto-reload value (between Min_Data=0 and Max_Data=65535) + */ +#define __LL_TIM_CALC_ARR(__TIMCLK__, __PSC__, __FREQ__) \ + ((((__TIMCLK__)/((__PSC__) + 1U)) >= (__FREQ__)) ? (((__TIMCLK__)/((__FREQ__) * ((__PSC__) + 1U))) - 1U) : 0U) + +/** + * @brief HELPER macro calculating the compare value required to achieve the required timer output compare + * active/inactive delay. + * @note ex: @ref __LL_TIM_CALC_DELAY (1000000, @ref LL_TIM_GetPrescaler (), 10); + * @param __TIMCLK__ timer input clock frequency (in Hz) + * @param __PSC__ prescaler + * @param __DELAY__ timer output compare active/inactive delay (in us) + * @retval Compare value (between Min_Data=0 and Max_Data=65535) + */ +#define __LL_TIM_CALC_DELAY(__TIMCLK__, __PSC__, __DELAY__) \ + ((uint32_t)(((uint64_t)(__TIMCLK__) * (uint64_t)(__DELAY__)) \ + / ((uint64_t)1000000U * (uint64_t)((__PSC__) + 1U)))) + +/** + * @brief HELPER macro calculating the auto-reload value to achieve the required pulse duration + * (when the timer operates in one pulse mode). + * @note ex: @ref __LL_TIM_CALC_PULSE (1000000, @ref LL_TIM_GetPrescaler (), 10, 20); + * @param __TIMCLK__ timer input clock frequency (in Hz) + * @param __PSC__ prescaler + * @param __DELAY__ timer output compare active/inactive delay (in us) + * @param __PULSE__ pulse duration (in us) + * @retval Auto-reload value (between Min_Data=0 and Max_Data=65535) + */ +#define __LL_TIM_CALC_PULSE(__TIMCLK__, __PSC__, __DELAY__, __PULSE__) \ + ((uint32_t)(__LL_TIM_CALC_DELAY((__TIMCLK__), (__PSC__), (__PULSE__)) \ + + __LL_TIM_CALC_DELAY((__TIMCLK__), (__PSC__), (__DELAY__)))) + +/** + * @brief HELPER macro retrieving the ratio of the input capture prescaler + * @note ex: @ref __LL_TIM_GET_ICPSC_RATIO (@ref LL_TIM_IC_GetPrescaler ()); + * @param __ICPSC__ This parameter can be one of the following values: + * @arg @ref LL_TIM_ICPSC_DIV1 + * @arg @ref LL_TIM_ICPSC_DIV2 + * @arg @ref LL_TIM_ICPSC_DIV4 + * @arg @ref LL_TIM_ICPSC_DIV8 + * @retval Input capture prescaler ratio (1, 2, 4 or 8) + */ +#define __LL_TIM_GET_ICPSC_RATIO(__ICPSC__) \ + ((uint32_t)(0x01U << (((__ICPSC__) >> 16U) >> TIM_CCMR1_IC1PSC_Pos))) + + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup TIM_LL_Exported_Functions TIM Exported Functions + * @{ + */ + +/** @defgroup TIM_LL_EF_Time_Base Time Base configuration + * @{ + */ +/** + * @brief Enable timer counter. + * @rmtoll CR1 CEN LL_TIM_EnableCounter + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableCounter(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->CR1, TIM_CR1_CEN); +} + +/** + * @brief Disable timer counter. + * @rmtoll CR1 CEN LL_TIM_DisableCounter + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableCounter(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->CR1, TIM_CR1_CEN); +} + +/** + * @brief Indicates whether the timer counter is enabled. + * @rmtoll CR1 CEN LL_TIM_IsEnabledCounter + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledCounter(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->CR1, TIM_CR1_CEN) == (TIM_CR1_CEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable update event generation. + * @rmtoll CR1 UDIS LL_TIM_EnableUpdateEvent + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableUpdateEvent(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->CR1, TIM_CR1_UDIS); +} + +/** + * @brief Disable update event generation. + * @rmtoll CR1 UDIS LL_TIM_DisableUpdateEvent + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableUpdateEvent(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->CR1, TIM_CR1_UDIS); +} + +/** + * @brief Indicates whether update event generation is enabled. + * @rmtoll CR1 UDIS LL_TIM_IsEnabledUpdateEvent + * @param TIMx Timer instance + * @retval Inverted state of bit (0 or 1). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledUpdateEvent(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->CR1, TIM_CR1_UDIS) == (uint32_t)RESET) ? 1UL : 0UL); +} + +/** + * @brief Set update event source + * @note Update event source set to LL_TIM_UPDATESOURCE_REGULAR: any of the following events + * generate an update interrupt or DMA request if enabled: + * - Counter overflow/underflow + * - Setting the UG bit + * - Update generation through the slave mode controller + * @note Update event source set to LL_TIM_UPDATESOURCE_COUNTER: only counter + * overflow/underflow generates an update interrupt or DMA request if enabled. + * @rmtoll CR1 URS LL_TIM_SetUpdateSource + * @param TIMx Timer instance + * @param UpdateSource This parameter can be one of the following values: + * @arg @ref LL_TIM_UPDATESOURCE_REGULAR + * @arg @ref LL_TIM_UPDATESOURCE_COUNTER + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetUpdateSource(TIM_TypeDef *TIMx, uint32_t UpdateSource) +{ + MODIFY_REG(TIMx->CR1, TIM_CR1_URS, UpdateSource); +} + +/** + * @brief Get actual event update source + * @rmtoll CR1 URS LL_TIM_GetUpdateSource + * @param TIMx Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_UPDATESOURCE_REGULAR + * @arg @ref LL_TIM_UPDATESOURCE_COUNTER + */ +__STATIC_INLINE uint32_t LL_TIM_GetUpdateSource(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_URS)); +} + +/** + * @brief Set one pulse mode (one shot v.s. repetitive). + * @rmtoll CR1 OPM LL_TIM_SetOnePulseMode + * @param TIMx Timer instance + * @param OnePulseMode This parameter can be one of the following values: + * @arg @ref LL_TIM_ONEPULSEMODE_SINGLE + * @arg @ref LL_TIM_ONEPULSEMODE_REPETITIVE + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetOnePulseMode(TIM_TypeDef *TIMx, uint32_t OnePulseMode) +{ + MODIFY_REG(TIMx->CR1, TIM_CR1_OPM, OnePulseMode); +} + +/** + * @brief Get actual one pulse mode. + * @rmtoll CR1 OPM LL_TIM_GetOnePulseMode + * @param TIMx Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_ONEPULSEMODE_SINGLE + * @arg @ref LL_TIM_ONEPULSEMODE_REPETITIVE + */ +__STATIC_INLINE uint32_t LL_TIM_GetOnePulseMode(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_OPM)); +} + +/** + * @brief Set the timer counter counting mode. + * @note Macro IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx) can be used to + * check whether or not the counter mode selection feature is supported + * by a timer instance. + * @note Switching from Center Aligned counter mode to Edge counter mode (or reverse) + * requires a timer reset to avoid unexpected direction + * due to DIR bit readonly in center aligned mode. + * @rmtoll CR1 DIR LL_TIM_SetCounterMode\n + * CR1 CMS LL_TIM_SetCounterMode + * @param TIMx Timer instance + * @param CounterMode This parameter can be one of the following values: + * @arg @ref LL_TIM_COUNTERMODE_UP + * @arg @ref LL_TIM_COUNTERMODE_DOWN + * @arg @ref LL_TIM_COUNTERMODE_CENTER_UP + * @arg @ref LL_TIM_COUNTERMODE_CENTER_DOWN + * @arg @ref LL_TIM_COUNTERMODE_CENTER_UP_DOWN + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetCounterMode(TIM_TypeDef *TIMx, uint32_t CounterMode) +{ + MODIFY_REG(TIMx->CR1, (TIM_CR1_DIR | TIM_CR1_CMS), CounterMode); +} + +/** + * @brief Get actual counter mode. + * @note Macro IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx) can be used to + * check whether or not the counter mode selection feature is supported + * by a timer instance. + * @rmtoll CR1 DIR LL_TIM_GetCounterMode\n + * CR1 CMS LL_TIM_GetCounterMode + * @param TIMx Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_COUNTERMODE_UP + * @arg @ref LL_TIM_COUNTERMODE_DOWN + * @arg @ref LL_TIM_COUNTERMODE_CENTER_UP + * @arg @ref LL_TIM_COUNTERMODE_CENTER_DOWN + * @arg @ref LL_TIM_COUNTERMODE_CENTER_UP_DOWN + */ +__STATIC_INLINE uint32_t LL_TIM_GetCounterMode(const TIM_TypeDef *TIMx) +{ + uint32_t counter_mode; + + counter_mode = (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_CMS)); + + if (counter_mode == 0U) + { + counter_mode = (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_DIR)); + } + + return counter_mode; +} + +/** + * @brief Enable auto-reload (ARR) preload. + * @rmtoll CR1 ARPE LL_TIM_EnableARRPreload + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableARRPreload(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->CR1, TIM_CR1_ARPE); +} + +/** + * @brief Disable auto-reload (ARR) preload. + * @rmtoll CR1 ARPE LL_TIM_DisableARRPreload + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableARRPreload(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->CR1, TIM_CR1_ARPE); +} + +/** + * @brief Indicates whether auto-reload (ARR) preload is enabled. + * @rmtoll CR1 ARPE LL_TIM_IsEnabledARRPreload + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledARRPreload(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->CR1, TIM_CR1_ARPE) == (TIM_CR1_ARPE)) ? 1UL : 0UL); +} + +/** + * @brief Set the division ratio between the timer clock and the sampling clock used by the dead-time generators + * (when supported) and the digital filters. + * @note Macro IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx) can be used to check + * whether or not the clock division feature is supported by the timer + * instance. + * @rmtoll CR1 CKD LL_TIM_SetClockDivision + * @param TIMx Timer instance + * @param ClockDivision This parameter can be one of the following values: + * @arg @ref LL_TIM_CLOCKDIVISION_DIV1 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV2 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV4 + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetClockDivision(TIM_TypeDef *TIMx, uint32_t ClockDivision) +{ + MODIFY_REG(TIMx->CR1, TIM_CR1_CKD, ClockDivision); +} + +/** + * @brief Get the actual division ratio between the timer clock and the sampling clock used by the dead-time + * generators (when supported) and the digital filters. + * @note Macro IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx) can be used to check + * whether or not the clock division feature is supported by the timer + * instance. + * @rmtoll CR1 CKD LL_TIM_GetClockDivision + * @param TIMx Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_CLOCKDIVISION_DIV1 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV2 + * @arg @ref LL_TIM_CLOCKDIVISION_DIV4 + */ +__STATIC_INLINE uint32_t LL_TIM_GetClockDivision(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_CKD)); +} + +/** + * @brief Set the counter value. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @rmtoll CNT CNT LL_TIM_SetCounter + * @param TIMx Timer instance + * @param Counter Counter value (between Min_Data=0 and Max_Data=0xFFFF or 0xFFFFFFFF) + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetCounter(TIM_TypeDef *TIMx, uint32_t Counter) +{ + WRITE_REG(TIMx->CNT, Counter); +} + +/** + * @brief Get the counter value. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @rmtoll CNT CNT LL_TIM_GetCounter + * @param TIMx Timer instance + * @retval Counter value (between Min_Data=0 and Max_Data=0xFFFF or 0xFFFFFFFF) + */ +__STATIC_INLINE uint32_t LL_TIM_GetCounter(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CNT)); +} + +/** + * @brief Get the current direction of the counter + * @rmtoll CR1 DIR LL_TIM_GetDirection + * @param TIMx Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_COUNTERDIRECTION_UP + * @arg @ref LL_TIM_COUNTERDIRECTION_DOWN + */ +__STATIC_INLINE uint32_t LL_TIM_GetDirection(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_DIR)); +} + +/** + * @brief Set the prescaler value. + * @note The counter clock frequency CK_CNT is equal to fCK_PSC / (PSC[15:0] + 1). + * @note The prescaler can be changed on the fly as this control register is buffered. The new + * prescaler ratio is taken into account at the next update event. + * @note Helper macro @ref __LL_TIM_CALC_PSC can be used to calculate the Prescaler parameter + * @rmtoll PSC PSC LL_TIM_SetPrescaler + * @param TIMx Timer instance + * @param Prescaler between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetPrescaler(TIM_TypeDef *TIMx, uint32_t Prescaler) +{ + WRITE_REG(TIMx->PSC, Prescaler); +} + +/** + * @brief Get the prescaler value. + * @rmtoll PSC PSC LL_TIM_GetPrescaler + * @param TIMx Timer instance + * @retval Prescaler value between Min_Data=0 and Max_Data=65535 + */ +__STATIC_INLINE uint32_t LL_TIM_GetPrescaler(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->PSC)); +} + +/** + * @brief Set the auto-reload value. + * @note The counter is blocked while the auto-reload value is null. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Helper macro @ref __LL_TIM_CALC_ARR can be used to calculate the AutoReload parameter + * @rmtoll ARR ARR LL_TIM_SetAutoReload + * @param TIMx Timer instance + * @param AutoReload between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetAutoReload(TIM_TypeDef *TIMx, uint32_t AutoReload) +{ + WRITE_REG(TIMx->ARR, AutoReload); +} + +/** + * @brief Get the auto-reload value. + * @rmtoll ARR ARR LL_TIM_GetAutoReload + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @param TIMx Timer instance + * @retval Auto-reload value + */ +__STATIC_INLINE uint32_t LL_TIM_GetAutoReload(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->ARR)); +} + +/** + * @brief Set the repetition counter value. + * @note For advanced timer instances RepetitionCounter can be up to 65535. + * @note Macro IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a repetition counter. + * @rmtoll RCR REP LL_TIM_SetRepetitionCounter + * @param TIMx Timer instance + * @param RepetitionCounter between Min_Data=0 and Max_Data=255 or 65535 for advanced timer. + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetRepetitionCounter(TIM_TypeDef *TIMx, uint32_t RepetitionCounter) +{ + WRITE_REG(TIMx->RCR, RepetitionCounter); +} + +/** + * @brief Get the repetition counter value. + * @note Macro IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a repetition counter. + * @rmtoll RCR REP LL_TIM_GetRepetitionCounter + * @param TIMx Timer instance + * @retval Repetition counter value + */ +__STATIC_INLINE uint32_t LL_TIM_GetRepetitionCounter(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->RCR)); +} + +/** + * @brief Force a continuous copy of the update interrupt flag (UIF) into the timer counter register (bit 31). + * @note This allows both the counter value and a potential roll-over condition signalled by the UIFCPY flag to be read + * in an atomic way. + * @rmtoll CR1 UIFREMAP LL_TIM_EnableUIFRemap + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableUIFRemap(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->CR1, TIM_CR1_UIFREMAP); +} + +/** + * @brief Disable update interrupt flag (UIF) remapping. + * @rmtoll CR1 UIFREMAP LL_TIM_DisableUIFRemap + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableUIFRemap(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->CR1, TIM_CR1_UIFREMAP); +} + +/** + * @brief Indicate whether update interrupt flag (UIF) copy is set. + * @param Counter Counter value + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsActiveUIFCPY(const uint32_t Counter) +{ + return (((Counter & TIM_CNT_UIFCPY) == (TIM_CNT_UIFCPY)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Capture_Compare Capture Compare configuration + * @{ + */ +/** + * @brief Enable the capture/compare control bits (CCxE, CCxNE and OCxM) preload. + * @note CCxE, CCxNE and OCxM bits are preloaded, after having been written, + * they are updated only when a commutation event (COM) occurs. + * @note Only on channels that have a complementary output. + * @note Macro IS_TIM_COMMUTATION_EVENT_INSTANCE(TIMx) can be used to check + * whether or not a timer instance is able to generate a commutation event. + * @rmtoll CR2 CCPC LL_TIM_CC_EnablePreload + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_EnablePreload(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->CR2, TIM_CR2_CCPC); +} + +/** + * @brief Disable the capture/compare control bits (CCxE, CCxNE and OCxM) preload. + * @note Macro IS_TIM_COMMUTATION_EVENT_INSTANCE(TIMx) can be used to check + * whether or not a timer instance is able to generate a commutation event. + * @rmtoll CR2 CCPC LL_TIM_CC_DisablePreload + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_DisablePreload(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->CR2, TIM_CR2_CCPC); +} + +/** + * @brief Set the updated source of the capture/compare control bits (CCxE, CCxNE and OCxM). + * @note Macro IS_TIM_COMMUTATION_EVENT_INSTANCE(TIMx) can be used to check + * whether or not a timer instance is able to generate a commutation event. + * @rmtoll CR2 CCUS LL_TIM_CC_SetUpdate + * @param TIMx Timer instance + * @param CCUpdateSource This parameter can be one of the following values: + * @arg @ref LL_TIM_CCUPDATESOURCE_COMG_ONLY + * @arg @ref LL_TIM_CCUPDATESOURCE_COMG_AND_TRGI + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_SetUpdate(TIM_TypeDef *TIMx, uint32_t CCUpdateSource) +{ + MODIFY_REG(TIMx->CR2, TIM_CR2_CCUS, CCUpdateSource); +} + +/** + * @brief Set the trigger of the capture/compare DMA request. + * @rmtoll CR2 CCDS LL_TIM_CC_SetDMAReqTrigger + * @param TIMx Timer instance + * @param DMAReqTrigger This parameter can be one of the following values: + * @arg @ref LL_TIM_CCDMAREQUEST_CC + * @arg @ref LL_TIM_CCDMAREQUEST_UPDATE + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_SetDMAReqTrigger(TIM_TypeDef *TIMx, uint32_t DMAReqTrigger) +{ + MODIFY_REG(TIMx->CR2, TIM_CR2_CCDS, DMAReqTrigger); +} + +/** + * @brief Get actual trigger of the capture/compare DMA request. + * @rmtoll CR2 CCDS LL_TIM_CC_GetDMAReqTrigger + * @param TIMx Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_CCDMAREQUEST_CC + * @arg @ref LL_TIM_CCDMAREQUEST_UPDATE + */ +__STATIC_INLINE uint32_t LL_TIM_CC_GetDMAReqTrigger(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_BIT(TIMx->CR2, TIM_CR2_CCDS)); +} + +/** + * @brief Set the lock level to freeze the + * configuration of several capture/compare parameters. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * the lock mechanism is supported by a timer instance. + * @rmtoll BDTR LOCK LL_TIM_CC_SetLockLevel + * @param TIMx Timer instance + * @param LockLevel This parameter can be one of the following values: + * @arg @ref LL_TIM_LOCKLEVEL_OFF + * @arg @ref LL_TIM_LOCKLEVEL_1 + * @arg @ref LL_TIM_LOCKLEVEL_2 + * @arg @ref LL_TIM_LOCKLEVEL_3 + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_SetLockLevel(TIM_TypeDef *TIMx, uint32_t LockLevel) +{ + MODIFY_REG(TIMx->BDTR, TIM_BDTR_LOCK, LockLevel); +} + +/** + * @brief Enable capture/compare channels. + * @rmtoll CCER CC1E LL_TIM_CC_EnableChannel\n + * CCER CC1NE LL_TIM_CC_EnableChannel\n + * CCER CC2E LL_TIM_CC_EnableChannel\n + * CCER CC2NE LL_TIM_CC_EnableChannel\n + * CCER CC3E LL_TIM_CC_EnableChannel\n + * CCER CC3NE LL_TIM_CC_EnableChannel\n + * CCER CC4E LL_TIM_CC_EnableChannel\n + * CCER CC5E LL_TIM_CC_EnableChannel\n + * CCER CC6E LL_TIM_CC_EnableChannel + * @param TIMx Timer instance + * @param Channels This parameter can be a combination of the following values: + * @arg @ref LL_TIM_CHANNEL_CH1 + * @arg @ref LL_TIM_CHANNEL_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_EnableChannel(TIM_TypeDef *TIMx, uint32_t Channels) +{ + SET_BIT(TIMx->CCER, Channels); +} + +/** + * @brief Disable capture/compare channels. + * @rmtoll CCER CC1E LL_TIM_CC_DisableChannel\n + * CCER CC1NE LL_TIM_CC_DisableChannel\n + * CCER CC2E LL_TIM_CC_DisableChannel\n + * CCER CC2NE LL_TIM_CC_DisableChannel\n + * CCER CC3E LL_TIM_CC_DisableChannel\n + * CCER CC3NE LL_TIM_CC_DisableChannel\n + * CCER CC4E LL_TIM_CC_DisableChannel\n + * CCER CC5E LL_TIM_CC_DisableChannel\n + * CCER CC6E LL_TIM_CC_DisableChannel + * @param TIMx Timer instance + * @param Channels This parameter can be a combination of the following values: + * @arg @ref LL_TIM_CHANNEL_CH1 + * @arg @ref LL_TIM_CHANNEL_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_CC_DisableChannel(TIM_TypeDef *TIMx, uint32_t Channels) +{ + CLEAR_BIT(TIMx->CCER, Channels); +} + +/** + * @brief Indicate whether channel(s) is(are) enabled. + * @rmtoll CCER CC1E LL_TIM_CC_IsEnabledChannel\n + * CCER CC1NE LL_TIM_CC_IsEnabledChannel\n + * CCER CC2E LL_TIM_CC_IsEnabledChannel\n + * CCER CC2NE LL_TIM_CC_IsEnabledChannel\n + * CCER CC3E LL_TIM_CC_IsEnabledChannel\n + * CCER CC3NE LL_TIM_CC_IsEnabledChannel\n + * CCER CC4E LL_TIM_CC_IsEnabledChannel\n + * CCER CC5E LL_TIM_CC_IsEnabledChannel\n + * CCER CC6E LL_TIM_CC_IsEnabledChannel + * @param TIMx Timer instance + * @param Channels This parameter can be a combination of the following values: + * @arg @ref LL_TIM_CHANNEL_CH1 + * @arg @ref LL_TIM_CHANNEL_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_CC_IsEnabledChannel(const TIM_TypeDef *TIMx, uint32_t Channels) +{ + return ((READ_BIT(TIMx->CCER, Channels) == (Channels)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Output_Channel Output channel configuration + * @{ + */ +/** + * @brief Configure an output channel. + * @rmtoll CCMR1 CC1S LL_TIM_OC_ConfigOutput\n + * CCMR1 CC2S LL_TIM_OC_ConfigOutput\n + * CCMR2 CC3S LL_TIM_OC_ConfigOutput\n + * CCMR2 CC4S LL_TIM_OC_ConfigOutput\n + * CCMR3 CC5S LL_TIM_OC_ConfigOutput\n + * CCMR3 CC6S LL_TIM_OC_ConfigOutput\n + * CCER CC1P LL_TIM_OC_ConfigOutput\n + * CCER CC2P LL_TIM_OC_ConfigOutput\n + * CCER CC3P LL_TIM_OC_ConfigOutput\n + * CCER CC4P LL_TIM_OC_ConfigOutput\n + * CCER CC5P LL_TIM_OC_ConfigOutput\n + * CCER CC6P LL_TIM_OC_ConfigOutput\n + * CR2 OIS1 LL_TIM_OC_ConfigOutput\n + * CR2 OIS2 LL_TIM_OC_ConfigOutput\n + * CR2 OIS3 LL_TIM_OC_ConfigOutput\n + * CR2 OIS4 LL_TIM_OC_ConfigOutput\n + * CR2 OIS5 LL_TIM_OC_ConfigOutput\n + * CR2 OIS6 LL_TIM_OC_ConfigOutput + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @param Configuration This parameter must be a combination of all the following values: + * @arg @ref LL_TIM_OCPOLARITY_HIGH or @ref LL_TIM_OCPOLARITY_LOW + * @arg @ref LL_TIM_OCIDLESTATE_LOW or @ref LL_TIM_OCIDLESTATE_HIGH + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_ConfigOutput(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t Configuration) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + CLEAR_BIT(*pReg, (TIM_CCMR1_CC1S << SHIFT_TAB_OCxx[iChannel])); + MODIFY_REG(TIMx->CCER, (TIM_CCER_CC1P << SHIFT_TAB_CCxP[iChannel]), + (Configuration & TIM_CCER_CC1P) << SHIFT_TAB_CCxP[iChannel]); + MODIFY_REG(TIMx->CR2, (TIM_CR2_OIS1 << SHIFT_TAB_OISx[iChannel]), + (Configuration & TIM_CR2_OIS1) << SHIFT_TAB_OISx[iChannel]); +} + +/** + * @brief Define the behavior of the output reference signal OCxREF from which + * OCx and OCxN (when relevant) are derived. + * @rmtoll CCMR1 OC1M LL_TIM_OC_SetMode\n + * CCMR1 OC2M LL_TIM_OC_SetMode\n + * CCMR2 OC3M LL_TIM_OC_SetMode\n + * CCMR2 OC4M LL_TIM_OC_SetMode\n + * CCMR3 OC5M LL_TIM_OC_SetMode\n + * CCMR3 OC6M LL_TIM_OC_SetMode + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_TIM_OCMODE_FROZEN + * @arg @ref LL_TIM_OCMODE_ACTIVE + * @arg @ref LL_TIM_OCMODE_INACTIVE + * @arg @ref LL_TIM_OCMODE_TOGGLE + * @arg @ref LL_TIM_OCMODE_FORCED_INACTIVE + * @arg @ref LL_TIM_OCMODE_FORCED_ACTIVE + * @arg @ref LL_TIM_OCMODE_PWM1 + * @arg @ref LL_TIM_OCMODE_PWM2 + * @arg @ref LL_TIM_OCMODE_RETRIG_OPM1 + * @arg @ref LL_TIM_OCMODE_RETRIG_OPM2 + * @arg @ref LL_TIM_OCMODE_COMBINED_PWM1 + * @arg @ref LL_TIM_OCMODE_COMBINED_PWM2 + * @arg @ref LL_TIM_OCMODE_ASSYMETRIC_PWM1 + * @arg @ref LL_TIM_OCMODE_ASSYMETRIC_PWM2 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetMode(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t Mode) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + MODIFY_REG(*pReg, ((TIM_CCMR1_OC1M | TIM_CCMR1_CC1S) << SHIFT_TAB_OCxx[iChannel]), Mode << SHIFT_TAB_OCxx[iChannel]); +} + +/** + * @brief Get the output compare mode of an output channel. + * @rmtoll CCMR1 OC1M LL_TIM_OC_GetMode\n + * CCMR1 OC2M LL_TIM_OC_GetMode\n + * CCMR2 OC3M LL_TIM_OC_GetMode\n + * CCMR2 OC4M LL_TIM_OC_GetMode\n + * CCMR3 OC5M LL_TIM_OC_GetMode\n + * CCMR3 OC6M LL_TIM_OC_GetMode + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_OCMODE_FROZEN + * @arg @ref LL_TIM_OCMODE_ACTIVE + * @arg @ref LL_TIM_OCMODE_INACTIVE + * @arg @ref LL_TIM_OCMODE_TOGGLE + * @arg @ref LL_TIM_OCMODE_FORCED_INACTIVE + * @arg @ref LL_TIM_OCMODE_FORCED_ACTIVE + * @arg @ref LL_TIM_OCMODE_PWM1 + * @arg @ref LL_TIM_OCMODE_PWM2 + * @arg @ref LL_TIM_OCMODE_RETRIG_OPM1 + * @arg @ref LL_TIM_OCMODE_RETRIG_OPM2 + * @arg @ref LL_TIM_OCMODE_COMBINED_PWM1 + * @arg @ref LL_TIM_OCMODE_COMBINED_PWM2 + * @arg @ref LL_TIM_OCMODE_ASSYMETRIC_PWM1 + * @arg @ref LL_TIM_OCMODE_ASSYMETRIC_PWM2 + */ +__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])); + return (READ_BIT(*pReg, ((TIM_CCMR1_OC1M | TIM_CCMR1_CC1S) << SHIFT_TAB_OCxx[iChannel])) >> SHIFT_TAB_OCxx[iChannel]); +} + +/** + * @brief Set the polarity of an output channel. + * @rmtoll CCER CC1P LL_TIM_OC_SetPolarity\n + * CCER CC1NP LL_TIM_OC_SetPolarity\n + * CCER CC2P LL_TIM_OC_SetPolarity\n + * CCER CC2NP LL_TIM_OC_SetPolarity\n + * CCER CC3P LL_TIM_OC_SetPolarity\n + * CCER CC3NP LL_TIM_OC_SetPolarity\n + * CCER CC4P LL_TIM_OC_SetPolarity\n + * CCER CC5P LL_TIM_OC_SetPolarity\n + * CCER CC6P LL_TIM_OC_SetPolarity + * @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_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_TIM_OCPOLARITY_HIGH + * @arg @ref LL_TIM_OCPOLARITY_LOW + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetPolarity(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t Polarity) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + MODIFY_REG(TIMx->CCER, (TIM_CCER_CC1P << SHIFT_TAB_CCxP[iChannel]), Polarity << SHIFT_TAB_CCxP[iChannel]); +} + +/** + * @brief Get the polarity of an output channel. + * @rmtoll CCER CC1P LL_TIM_OC_GetPolarity\n + * CCER CC1NP LL_TIM_OC_GetPolarity\n + * CCER CC2P LL_TIM_OC_GetPolarity\n + * CCER CC2NP LL_TIM_OC_GetPolarity\n + * CCER CC3P LL_TIM_OC_GetPolarity\n + * CCER CC3NP LL_TIM_OC_GetPolarity\n + * CCER CC4P LL_TIM_OC_GetPolarity\n + * CCER CC5P LL_TIM_OC_GetPolarity\n + * CCER CC6P LL_TIM_OC_GetPolarity + * @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_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_OCPOLARITY_HIGH + * @arg @ref LL_TIM_OCPOLARITY_LOW + */ +__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]); +} + +/** + * @brief Set the IDLE state of an output channel + * @note This function is significant only for the timer instances + * supporting the break feature. Macro IS_TIM_BREAK_INSTANCE(TIMx) + * can be used to check whether or not a timer instance provides + * a break input. + * @rmtoll CR2 OIS1 LL_TIM_OC_SetIdleState\n + * CR2 OIS2N LL_TIM_OC_SetIdleState\n + * CR2 OIS2 LL_TIM_OC_SetIdleState\n + * CR2 OIS2N LL_TIM_OC_SetIdleState\n + * CR2 OIS3 LL_TIM_OC_SetIdleState\n + * CR2 OIS3N LL_TIM_OC_SetIdleState\n + * CR2 OIS4 LL_TIM_OC_SetIdleState\n + * CR2 OIS5 LL_TIM_OC_SetIdleState\n + * CR2 OIS6 LL_TIM_OC_SetIdleState + * @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_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @param IdleState This parameter can be one of the following values: + * @arg @ref LL_TIM_OCIDLESTATE_LOW + * @arg @ref LL_TIM_OCIDLESTATE_HIGH + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetIdleState(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t IdleState) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + MODIFY_REG(TIMx->CR2, (TIM_CR2_OIS1 << SHIFT_TAB_OISx[iChannel]), IdleState << SHIFT_TAB_OISx[iChannel]); +} + +/** + * @brief Get the IDLE state of an output channel + * @rmtoll CR2 OIS1 LL_TIM_OC_GetIdleState\n + * CR2 OIS2N LL_TIM_OC_GetIdleState\n + * CR2 OIS2 LL_TIM_OC_GetIdleState\n + * CR2 OIS2N LL_TIM_OC_GetIdleState\n + * CR2 OIS3 LL_TIM_OC_GetIdleState\n + * CR2 OIS3N LL_TIM_OC_GetIdleState\n + * CR2 OIS4 LL_TIM_OC_GetIdleState\n + * CR2 OIS5 LL_TIM_OC_GetIdleState\n + * CR2 OIS6 LL_TIM_OC_GetIdleState + * @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_CH1N + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH2N + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH3N + * @arg @ref LL_TIM_CHANNEL_CH4 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_OCIDLESTATE_LOW + * @arg @ref LL_TIM_OCIDLESTATE_HIGH + */ +__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]); +} + +/** + * @brief Enable fast mode for the output channel. + * @note Acts only if the channel is configured in PWM1 or PWM2 mode. + * @rmtoll CCMR1 OC1FE LL_TIM_OC_EnableFast\n + * CCMR1 OC2FE LL_TIM_OC_EnableFast\n + * CCMR2 OC3FE LL_TIM_OC_EnableFast\n + * CCMR2 OC4FE LL_TIM_OC_EnableFast\n + * CCMR3 OC5FE LL_TIM_OC_EnableFast\n + * CCMR3 OC6FE LL_TIM_OC_EnableFast + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_EnableFast(TIM_TypeDef *TIMx, uint32_t Channel) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + SET_BIT(*pReg, (TIM_CCMR1_OC1FE << SHIFT_TAB_OCxx[iChannel])); + +} + +/** + * @brief Disable fast mode for the output channel. + * @rmtoll CCMR1 OC1FE LL_TIM_OC_DisableFast\n + * CCMR1 OC2FE LL_TIM_OC_DisableFast\n + * CCMR2 OC3FE LL_TIM_OC_DisableFast\n + * CCMR2 OC4FE LL_TIM_OC_DisableFast\n + * CCMR3 OC5FE LL_TIM_OC_DisableFast\n + * CCMR3 OC6FE LL_TIM_OC_DisableFast + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_DisableFast(TIM_TypeDef *TIMx, uint32_t Channel) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + CLEAR_BIT(*pReg, (TIM_CCMR1_OC1FE << SHIFT_TAB_OCxx[iChannel])); + +} + +/** + * @brief Indicates whether fast mode is enabled for the output channel. + * @rmtoll CCMR1 OC1FE LL_TIM_OC_IsEnabledFast\n + * CCMR1 OC2FE LL_TIM_OC_IsEnabledFast\n + * CCMR2 OC3FE LL_TIM_OC_IsEnabledFast\n + * CCMR2 OC4FE LL_TIM_OC_IsEnabledFast\n + * CCMR3 OC5FE LL_TIM_OC_IsEnabledFast\n + * CCMR3 OC6FE LL_TIM_OC_IsEnabledFast + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_OC_IsEnabledFast(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])); + uint32_t bitfield = TIM_CCMR1_OC1FE << SHIFT_TAB_OCxx[iChannel]; + return ((READ_BIT(*pReg, bitfield) == bitfield) ? 1UL : 0UL); +} + +/** + * @brief Enable compare register (TIMx_CCRx) preload for the output channel. + * @rmtoll CCMR1 OC1PE LL_TIM_OC_EnablePreload\n + * CCMR1 OC2PE LL_TIM_OC_EnablePreload\n + * CCMR2 OC3PE LL_TIM_OC_EnablePreload\n + * CCMR2 OC4PE LL_TIM_OC_EnablePreload\n + * CCMR3 OC5PE LL_TIM_OC_EnablePreload\n + * CCMR3 OC6PE LL_TIM_OC_EnablePreload + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_EnablePreload(TIM_TypeDef *TIMx, uint32_t Channel) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + SET_BIT(*pReg, (TIM_CCMR1_OC1PE << SHIFT_TAB_OCxx[iChannel])); +} + +/** + * @brief Disable compare register (TIMx_CCRx) preload for the output channel. + * @rmtoll CCMR1 OC1PE LL_TIM_OC_DisablePreload\n + * CCMR1 OC2PE LL_TIM_OC_DisablePreload\n + * CCMR2 OC3PE LL_TIM_OC_DisablePreload\n + * CCMR2 OC4PE LL_TIM_OC_DisablePreload\n + * CCMR3 OC5PE LL_TIM_OC_DisablePreload\n + * CCMR3 OC6PE LL_TIM_OC_DisablePreload + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_DisablePreload(TIM_TypeDef *TIMx, uint32_t Channel) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + CLEAR_BIT(*pReg, (TIM_CCMR1_OC1PE << SHIFT_TAB_OCxx[iChannel])); +} + +/** + * @brief Indicates whether compare register (TIMx_CCRx) preload is enabled for the output channel. + * @rmtoll CCMR1 OC1PE LL_TIM_OC_IsEnabledPreload\n + * CCMR1 OC2PE LL_TIM_OC_IsEnabledPreload\n + * CCMR2 OC3PE LL_TIM_OC_IsEnabledPreload\n + * CCMR2 OC4PE LL_TIM_OC_IsEnabledPreload\n + * CCMR3 OC5PE LL_TIM_OC_IsEnabledPreload\n + * CCMR3 OC6PE LL_TIM_OC_IsEnabledPreload + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_OC_IsEnabledPreload(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])); + uint32_t bitfield = TIM_CCMR1_OC1PE << SHIFT_TAB_OCxx[iChannel]; + return ((READ_BIT(*pReg, bitfield) == bitfield) ? 1UL : 0UL); +} + +/** + * @brief Enable clearing the output channel on an external event. + * @note This function can only be used in Output compare and PWM modes. It does not work in Forced mode. + * @note Macro IS_TIM_OCXREF_CLEAR_INSTANCE(TIMx) can be used to check whether + * or not a timer instance can clear the OCxREF signal on an external event. + * @rmtoll CCMR1 OC1CE LL_TIM_OC_EnableClear\n + * CCMR1 OC2CE LL_TIM_OC_EnableClear\n + * CCMR2 OC3CE LL_TIM_OC_EnableClear\n + * CCMR2 OC4CE LL_TIM_OC_EnableClear\n + * CCMR3 OC5CE LL_TIM_OC_EnableClear\n + * CCMR3 OC6CE LL_TIM_OC_EnableClear + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_EnableClear(TIM_TypeDef *TIMx, uint32_t Channel) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + SET_BIT(*pReg, (TIM_CCMR1_OC1CE << SHIFT_TAB_OCxx[iChannel])); +} + +/** + * @brief Disable clearing the output channel on an external event. + * @note Macro IS_TIM_OCXREF_CLEAR_INSTANCE(TIMx) can be used to check whether + * or not a timer instance can clear the OCxREF signal on an external event. + * @rmtoll CCMR1 OC1CE LL_TIM_OC_DisableClear\n + * CCMR1 OC2CE LL_TIM_OC_DisableClear\n + * CCMR2 OC3CE LL_TIM_OC_DisableClear\n + * CCMR2 OC4CE LL_TIM_OC_DisableClear\n + * CCMR3 OC5CE LL_TIM_OC_DisableClear\n + * CCMR3 OC6CE LL_TIM_OC_DisableClear + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_DisableClear(TIM_TypeDef *TIMx, uint32_t Channel) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + CLEAR_BIT(*pReg, (TIM_CCMR1_OC1CE << SHIFT_TAB_OCxx[iChannel])); +} + +/** + * @brief Indicates clearing the output channel on an external event is enabled for the output channel. + * @note This function enables clearing the output channel on an external event. + * @note This function can only be used in Output compare and PWM modes. It does not work in Forced mode. + * @note Macro IS_TIM_OCXREF_CLEAR_INSTANCE(TIMx) can be used to check whether + * or not a timer instance can clear the OCxREF signal on an external event. + * @rmtoll CCMR1 OC1CE LL_TIM_OC_IsEnabledClear\n + * CCMR1 OC2CE LL_TIM_OC_IsEnabledClear\n + * CCMR2 OC3CE LL_TIM_OC_IsEnabledClear\n + * CCMR2 OC4CE LL_TIM_OC_IsEnabledClear\n + * CCMR3 OC5CE LL_TIM_OC_IsEnabledClear\n + * CCMR3 OC6CE LL_TIM_OC_IsEnabledClear + * @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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_OC_IsEnabledClear(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])); + uint32_t bitfield = TIM_CCMR1_OC1CE << SHIFT_TAB_OCxx[iChannel]; + return ((READ_BIT(*pReg, bitfield) == bitfield) ? 1UL : 0UL); +} + +/** + * @brief Set the dead-time delay (delay inserted between the rising edge of the OCxREF signal and the rising edge of + * the Ocx and OCxN signals). + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * dead-time insertion feature is supported by a timer instance. + * @note Helper macro @ref __LL_TIM_CALC_DEADTIME can be used to calculate the DeadTime parameter + * @rmtoll BDTR DTG LL_TIM_OC_SetDeadTime + * @param TIMx Timer instance + * @param DeadTime between Min_Data=0 and Max_Data=255 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetDeadTime(TIM_TypeDef *TIMx, uint32_t DeadTime) +{ + MODIFY_REG(TIMx->BDTR, TIM_BDTR_DTG, DeadTime); +} + +/** + * @brief Set compare value for output channel 1 (TIMx_CCR1). + * @note In 32-bit timer implementations compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC1_INSTANCE(TIMx) can be used to check whether or not + * output channel 1 is supported by a timer instance. + * @rmtoll CCR1 CCR1 LL_TIM_OC_SetCompareCH1 + * @param TIMx Timer instance + * @param CompareValue between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetCompareCH1(TIM_TypeDef *TIMx, uint32_t CompareValue) +{ + WRITE_REG(TIMx->CCR1, CompareValue); +} + +/** + * @brief Set compare value for output channel 2 (TIMx_CCR2). + * @note In 32-bit timer implementations compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC2_INSTANCE(TIMx) can be used to check whether or not + * output channel 2 is supported by a timer instance. + * @rmtoll CCR2 CCR2 LL_TIM_OC_SetCompareCH2 + * @param TIMx Timer instance + * @param CompareValue between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetCompareCH2(TIM_TypeDef *TIMx, uint32_t CompareValue) +{ + WRITE_REG(TIMx->CCR2, CompareValue); +} + +/** + * @brief Set compare value for output channel 3 (TIMx_CCR3). + * @note In 32-bit timer implementations compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC3_INSTANCE(TIMx) can be used to check whether or not + * output channel is supported by a timer instance. + * @rmtoll CCR3 CCR3 LL_TIM_OC_SetCompareCH3 + * @param TIMx Timer instance + * @param CompareValue between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetCompareCH3(TIM_TypeDef *TIMx, uint32_t CompareValue) +{ + WRITE_REG(TIMx->CCR3, CompareValue); +} + +/** + * @brief Set compare value for output channel 4 (TIMx_CCR4). + * @note In 32-bit timer implementations compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC4_INSTANCE(TIMx) can be used to check whether or not + * output channel 4 is supported by a timer instance. + * @rmtoll CCR4 CCR4 LL_TIM_OC_SetCompareCH4 + * @param TIMx Timer instance + * @param CompareValue between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetCompareCH4(TIM_TypeDef *TIMx, uint32_t CompareValue) +{ + WRITE_REG(TIMx->CCR4, CompareValue); +} + +/** + * @brief Set compare value for output channel 5 (TIMx_CCR5). + * @note Macro IS_TIM_CC5_INSTANCE(TIMx) can be used to check whether or not + * output channel 5 is supported by a timer instance. + * @rmtoll CCR5 CCR5 LL_TIM_OC_SetCompareCH5 + * @param TIMx Timer instance + * @param CompareValue between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetCompareCH5(TIM_TypeDef *TIMx, uint32_t CompareValue) +{ + MODIFY_REG(TIMx->CCR5, TIM_CCR5_CCR5, CompareValue); +} + +/** + * @brief Set compare value for output channel 6 (TIMx_CCR6). + * @note Macro IS_TIM_CC6_INSTANCE(TIMx) can be used to check whether or not + * output channel 6 is supported by a timer instance. + * @rmtoll CCR6 CCR6 LL_TIM_OC_SetCompareCH6 + * @param TIMx Timer instance + * @param CompareValue between Min_Data=0 and Max_Data=65535 + * @retval None + */ +__STATIC_INLINE void LL_TIM_OC_SetCompareCH6(TIM_TypeDef *TIMx, uint32_t CompareValue) +{ + WRITE_REG(TIMx->CCR6, CompareValue); +} + +/** + * @brief Get compare value (TIMx_CCR1) set for output channel 1. + * @note In 32-bit timer implementations returned compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC1_INSTANCE(TIMx) can be used to check whether or not + * output channel 1 is supported by a timer instance. + * @rmtoll CCR1 CCR1 LL_TIM_OC_GetCompareCH1 + * @param TIMx Timer instance + * @retval CompareValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH1(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR1)); +} + +/** + * @brief Get compare value (TIMx_CCR2) set for output channel 2. + * @note In 32-bit timer implementations returned compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC2_INSTANCE(TIMx) can be used to check whether or not + * output channel 2 is supported by a timer instance. + * @rmtoll CCR2 CCR2 LL_TIM_OC_GetCompareCH2 + * @param TIMx Timer instance + * @retval CompareValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH2(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR2)); +} + +/** + * @brief Get compare value (TIMx_CCR3) set for output channel 3. + * @note In 32-bit timer implementations returned compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC3_INSTANCE(TIMx) can be used to check whether or not + * output channel 3 is supported by a timer instance. + * @rmtoll CCR3 CCR3 LL_TIM_OC_GetCompareCH3 + * @param TIMx Timer instance + * @retval CompareValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH3(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR3)); +} + +/** + * @brief Get compare value (TIMx_CCR4) set for output channel 4. + * @note In 32-bit timer implementations returned compare value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC4_INSTANCE(TIMx) can be used to check whether or not + * output channel 4 is supported by a timer instance. + * @rmtoll CCR4 CCR4 LL_TIM_OC_GetCompareCH4 + * @param TIMx Timer instance + * @retval CompareValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH4(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR4)); +} + +/** + * @brief Get compare value (TIMx_CCR5) set for output channel 5. + * @note Macro IS_TIM_CC5_INSTANCE(TIMx) can be used to check whether or not + * output channel 5 is supported by a timer instance. + * @rmtoll CCR5 CCR5 LL_TIM_OC_GetCompareCH5 + * @param TIMx Timer instance + * @retval CompareValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH5(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_BIT(TIMx->CCR5, TIM_CCR5_CCR5)); +} + +/** + * @brief Get compare value (TIMx_CCR6) set for output channel 6. + * @note Macro IS_TIM_CC6_INSTANCE(TIMx) can be used to check whether or not + * output channel 6 is supported by a timer instance. + * @rmtoll CCR6 CCR6 LL_TIM_OC_GetCompareCH6 + * @param TIMx Timer instance + * @retval CompareValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH6(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR6)); +} + +/** + * @brief Select on which reference signal the OC5REF is combined to. + * @note Macro IS_TIM_COMBINED3PHASEPWM_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports the combined 3-phase PWM mode. + * @rmtoll CCR5 GC5C3 LL_TIM_SetCH5CombinedChannels\n + * CCR5 GC5C2 LL_TIM_SetCH5CombinedChannels\n + * CCR5 GC5C1 LL_TIM_SetCH5CombinedChannels + * @param TIMx Timer instance + * @param GroupCH5 This parameter can be a combination of the following values: + * @arg @ref LL_TIM_GROUPCH5_NONE + * @arg @ref LL_TIM_GROUPCH5_OC1REFC + * @arg @ref LL_TIM_GROUPCH5_OC2REFC + * @arg @ref LL_TIM_GROUPCH5_OC3REFC + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetCH5CombinedChannels(TIM_TypeDef *TIMx, uint32_t GroupCH5) +{ + MODIFY_REG(TIMx->CCR5, (TIM_CCR5_GC5C3 | TIM_CCR5_GC5C2 | TIM_CCR5_GC5C1), GroupCH5); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Input_Channel Input channel configuration + * @{ + */ +/** + * @brief Configure input channel. + * @rmtoll CCMR1 CC1S LL_TIM_IC_Config\n + * CCMR1 IC1PSC LL_TIM_IC_Config\n + * CCMR1 IC1F LL_TIM_IC_Config\n + * CCMR1 CC2S LL_TIM_IC_Config\n + * CCMR1 IC2PSC LL_TIM_IC_Config\n + * CCMR1 IC2F LL_TIM_IC_Config\n + * CCMR2 CC3S LL_TIM_IC_Config\n + * CCMR2 IC3PSC LL_TIM_IC_Config\n + * CCMR2 IC3F LL_TIM_IC_Config\n + * CCMR2 CC4S LL_TIM_IC_Config\n + * CCMR2 IC4PSC LL_TIM_IC_Config\n + * CCMR2 IC4F LL_TIM_IC_Config\n + * CCER CC1P LL_TIM_IC_Config\n + * CCER CC1NP LL_TIM_IC_Config\n + * CCER CC2P LL_TIM_IC_Config\n + * CCER CC2NP LL_TIM_IC_Config\n + * CCER CC3P LL_TIM_IC_Config\n + * CCER CC3NP LL_TIM_IC_Config\n + * CCER CC4P LL_TIM_IC_Config\n + * CCER CC4NP LL_TIM_IC_Config + * @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 Configuration This parameter must be a combination of all the following values: + * @arg @ref LL_TIM_ACTIVEINPUT_DIRECTTI or @ref LL_TIM_ACTIVEINPUT_INDIRECTTI or @ref LL_TIM_ACTIVEINPUT_TRC + * @arg @ref LL_TIM_ICPSC_DIV1 or ... or @ref LL_TIM_ICPSC_DIV8 + * @arg @ref LL_TIM_IC_FILTER_FDIV1 or ... or @ref LL_TIM_IC_FILTER_FDIV32_N8 + * @arg @ref LL_TIM_IC_POLARITY_RISING or @ref LL_TIM_IC_POLARITY_FALLING or @ref LL_TIM_IC_POLARITY_BOTHEDGE + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_Config(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t Configuration) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + MODIFY_REG(*pReg, ((TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC | TIM_CCMR1_CC1S) << SHIFT_TAB_ICxx[iChannel]), + ((Configuration >> 16U) & (TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC | TIM_CCMR1_CC1S)) \ + << SHIFT_TAB_ICxx[iChannel]); + MODIFY_REG(TIMx->CCER, ((TIM_CCER_CC1NP | TIM_CCER_CC1P) << SHIFT_TAB_CCxP[iChannel]), + (Configuration & (TIM_CCER_CC1NP | TIM_CCER_CC1P)) << SHIFT_TAB_CCxP[iChannel]); +} + +/** + * @brief Set the active input. + * @rmtoll CCMR1 CC1S LL_TIM_IC_SetActiveInput\n + * CCMR1 CC2S LL_TIM_IC_SetActiveInput\n + * CCMR2 CC3S LL_TIM_IC_SetActiveInput\n + * CCMR2 CC4S LL_TIM_IC_SetActiveInput + * @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 ICActiveInput This parameter can be one of the following values: + * @arg @ref LL_TIM_ACTIVEINPUT_DIRECTTI + * @arg @ref LL_TIM_ACTIVEINPUT_INDIRECTTI + * @arg @ref LL_TIM_ACTIVEINPUT_TRC + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_SetActiveInput(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ICActiveInput) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + MODIFY_REG(*pReg, ((TIM_CCMR1_CC1S) << SHIFT_TAB_ICxx[iChannel]), (ICActiveInput >> 16U) << SHIFT_TAB_ICxx[iChannel]); +} + +/** + * @brief Get the current active input. + * @rmtoll CCMR1 CC1S LL_TIM_IC_GetActiveInput\n + * CCMR1 CC2S LL_TIM_IC_GetActiveInput\n + * CCMR2 CC3S LL_TIM_IC_GetActiveInput\n + * CCMR2 CC4S LL_TIM_IC_GetActiveInput + * @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 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_ACTIVEINPUT_DIRECTTI + * @arg @ref LL_TIM_ACTIVEINPUT_INDIRECTTI + * @arg @ref LL_TIM_ACTIVEINPUT_TRC + */ +__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])); + return ((READ_BIT(*pReg, ((TIM_CCMR1_CC1S) << SHIFT_TAB_ICxx[iChannel])) >> SHIFT_TAB_ICxx[iChannel]) << 16U); +} + +/** + * @brief Set the prescaler of input channel. + * @rmtoll CCMR1 IC1PSC LL_TIM_IC_SetPrescaler\n + * CCMR1 IC2PSC LL_TIM_IC_SetPrescaler\n + * CCMR2 IC3PSC LL_TIM_IC_SetPrescaler\n + * CCMR2 IC4PSC LL_TIM_IC_SetPrescaler + * @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 ICPrescaler This parameter can be one of the following values: + * @arg @ref LL_TIM_ICPSC_DIV1 + * @arg @ref LL_TIM_ICPSC_DIV2 + * @arg @ref LL_TIM_ICPSC_DIV4 + * @arg @ref LL_TIM_ICPSC_DIV8 + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_SetPrescaler(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ICPrescaler) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + MODIFY_REG(*pReg, ((TIM_CCMR1_IC1PSC) << SHIFT_TAB_ICxx[iChannel]), (ICPrescaler >> 16U) << SHIFT_TAB_ICxx[iChannel]); +} + +/** + * @brief Get the current prescaler value acting on an input channel. + * @rmtoll CCMR1 IC1PSC LL_TIM_IC_GetPrescaler\n + * CCMR1 IC2PSC LL_TIM_IC_GetPrescaler\n + * CCMR2 IC3PSC LL_TIM_IC_GetPrescaler\n + * CCMR2 IC4PSC LL_TIM_IC_GetPrescaler + * @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 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_ICPSC_DIV1 + * @arg @ref LL_TIM_ICPSC_DIV2 + * @arg @ref LL_TIM_ICPSC_DIV4 + * @arg @ref LL_TIM_ICPSC_DIV8 + */ +__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])); + return ((READ_BIT(*pReg, ((TIM_CCMR1_IC1PSC) << SHIFT_TAB_ICxx[iChannel])) >> SHIFT_TAB_ICxx[iChannel]) << 16U); +} + +/** + * @brief Set the input filter duration. + * @rmtoll CCMR1 IC1F LL_TIM_IC_SetFilter\n + * CCMR1 IC2F LL_TIM_IC_SetFilter\n + * CCMR2 IC3F LL_TIM_IC_SetFilter\n + * CCMR2 IC4F LL_TIM_IC_SetFilter + * @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 ICFilter This parameter can be one of the following values: + * @arg @ref LL_TIM_IC_FILTER_FDIV1 + * @arg @ref LL_TIM_IC_FILTER_FDIV1_N2 + * @arg @ref LL_TIM_IC_FILTER_FDIV1_N4 + * @arg @ref LL_TIM_IC_FILTER_FDIV1_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV2_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV2_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV4_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV4_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV8_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV8_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV16_N5 + * @arg @ref LL_TIM_IC_FILTER_FDIV16_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV16_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV32_N5 + * @arg @ref LL_TIM_IC_FILTER_FDIV32_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV32_N8 + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_SetFilter(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ICFilter) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); + MODIFY_REG(*pReg, ((TIM_CCMR1_IC1F) << SHIFT_TAB_ICxx[iChannel]), (ICFilter >> 16U) << SHIFT_TAB_ICxx[iChannel]); +} + +/** + * @brief Get the input filter duration. + * @rmtoll CCMR1 IC1F LL_TIM_IC_GetFilter\n + * CCMR1 IC2F LL_TIM_IC_GetFilter\n + * CCMR2 IC3F LL_TIM_IC_GetFilter\n + * CCMR2 IC4F LL_TIM_IC_GetFilter + * @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 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_IC_FILTER_FDIV1 + * @arg @ref LL_TIM_IC_FILTER_FDIV1_N2 + * @arg @ref LL_TIM_IC_FILTER_FDIV1_N4 + * @arg @ref LL_TIM_IC_FILTER_FDIV1_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV2_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV2_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV4_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV4_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV8_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV8_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV16_N5 + * @arg @ref LL_TIM_IC_FILTER_FDIV16_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV16_N8 + * @arg @ref LL_TIM_IC_FILTER_FDIV32_N5 + * @arg @ref LL_TIM_IC_FILTER_FDIV32_N6 + * @arg @ref LL_TIM_IC_FILTER_FDIV32_N8 + */ +__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])); + return ((READ_BIT(*pReg, ((TIM_CCMR1_IC1F) << SHIFT_TAB_ICxx[iChannel])) >> SHIFT_TAB_ICxx[iChannel]) << 16U); +} + +/** + * @brief Set the input channel polarity. + * @rmtoll CCER CC1P LL_TIM_IC_SetPolarity\n + * CCER CC1NP LL_TIM_IC_SetPolarity\n + * CCER CC2P LL_TIM_IC_SetPolarity\n + * CCER CC2NP LL_TIM_IC_SetPolarity\n + * CCER CC3P LL_TIM_IC_SetPolarity\n + * CCER CC3NP LL_TIM_IC_SetPolarity\n + * CCER CC4P LL_TIM_IC_SetPolarity\n + * CCER CC4NP LL_TIM_IC_SetPolarity + * @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 ICPolarity This parameter can be one of the following values: + * @arg @ref LL_TIM_IC_POLARITY_RISING + * @arg @ref LL_TIM_IC_POLARITY_FALLING + * @arg @ref LL_TIM_IC_POLARITY_BOTHEDGE + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_SetPolarity(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ICPolarity) +{ + uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); + MODIFY_REG(TIMx->CCER, ((TIM_CCER_CC1NP | TIM_CCER_CC1P) << SHIFT_TAB_CCxP[iChannel]), + ICPolarity << SHIFT_TAB_CCxP[iChannel]); +} + +/** + * @brief Get the current input channel polarity. + * @rmtoll CCER CC1P LL_TIM_IC_GetPolarity\n + * CCER CC1NP LL_TIM_IC_GetPolarity\n + * CCER CC2P LL_TIM_IC_GetPolarity\n + * CCER CC2NP LL_TIM_IC_GetPolarity\n + * CCER CC3P LL_TIM_IC_GetPolarity\n + * CCER CC3NP LL_TIM_IC_GetPolarity\n + * CCER CC4P LL_TIM_IC_GetPolarity\n + * CCER CC4NP LL_TIM_IC_GetPolarity + * @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 + * @retval Returned value can be one of the following values: + * @arg @ref LL_TIM_IC_POLARITY_RISING + * @arg @ref LL_TIM_IC_POLARITY_FALLING + * @arg @ref LL_TIM_IC_POLARITY_BOTHEDGE + */ +__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])) >> + SHIFT_TAB_CCxP[iChannel]); +} + +/** + * @brief Connect the TIMx_CH1, CH2 and CH3 pins to the TI1 input (XOR combination). + * @note Macro IS_TIM_XOR_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides an XOR input. + * @rmtoll CR2 TI1S LL_TIM_IC_EnableXORCombination + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_EnableXORCombination(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->CR2, TIM_CR2_TI1S); +} + +/** + * @brief Disconnect the TIMx_CH1, CH2 and CH3 pins from the TI1 input. + * @note Macro IS_TIM_XOR_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides an XOR input. + * @rmtoll CR2 TI1S LL_TIM_IC_DisableXORCombination + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_IC_DisableXORCombination(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->CR2, TIM_CR2_TI1S); +} + +/** + * @brief Indicates whether the TIMx_CH1, CH2 and CH3 pins are connectected to the TI1 input. + * @note Macro IS_TIM_XOR_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides an XOR input. + * @rmtoll CR2 TI1S LL_TIM_IC_IsEnabledXORCombination + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IC_IsEnabledXORCombination(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->CR2, TIM_CR2_TI1S) == (TIM_CR2_TI1S)) ? 1UL : 0UL); +} + +/** + * @brief Get captured value for input channel 1. + * @note In 32-bit timer implementations returned captured value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC1_INSTANCE(TIMx) can be used to check whether or not + * input channel 1 is supported by a timer instance. + * @rmtoll CCR1 CCR1 LL_TIM_IC_GetCaptureCH1 + * @param TIMx Timer instance + * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH1(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR1)); +} + +/** + * @brief Get captured value for input channel 2. + * @note In 32-bit timer implementations returned captured value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC2_INSTANCE(TIMx) can be used to check whether or not + * input channel 2 is supported by a timer instance. + * @rmtoll CCR2 CCR2 LL_TIM_IC_GetCaptureCH2 + * @param TIMx Timer instance + * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH2(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR2)); +} + +/** + * @brief Get captured value for input channel 3. + * @note In 32-bit timer implementations returned captured value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC3_INSTANCE(TIMx) can be used to check whether or not + * input channel 3 is supported by a timer instance. + * @rmtoll CCR3 CCR3 LL_TIM_IC_GetCaptureCH3 + * @param TIMx Timer instance + * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH3(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR3)); +} + +/** + * @brief Get captured value for input channel 4. + * @note In 32-bit timer implementations returned captured value can be between 0x00000000 and 0xFFFFFFFF. + * @note Macro IS_TIM_32B_COUNTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports a 32 bits counter. + * @note Macro IS_TIM_CC4_INSTANCE(TIMx) can be used to check whether or not + * input channel 4 is supported by a timer instance. + * @rmtoll CCR4 CCR4 LL_TIM_IC_GetCaptureCH4 + * @param TIMx Timer instance + * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) + */ +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH4(const TIM_TypeDef *TIMx) +{ + return (uint32_t)(READ_REG(TIMx->CCR4)); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Clock_Selection Counter clock selection + * @{ + */ +/** + * @brief Enable external clock mode 2. + * @note When external clock mode 2 is enabled the counter is clocked by any active edge on the ETRF signal. + * @note Macro IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports external clock mode2. + * @rmtoll SMCR ECE LL_TIM_EnableExternalClock + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableExternalClock(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->SMCR, TIM_SMCR_ECE); +} + +/** + * @brief Disable external clock mode 2. + * @note Macro IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports external clock mode2. + * @rmtoll SMCR ECE LL_TIM_DisableExternalClock + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableExternalClock(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->SMCR, TIM_SMCR_ECE); +} + +/** + * @brief Indicate whether external clock mode 2 is enabled. + * @note Macro IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports external clock mode2. + * @rmtoll SMCR ECE LL_TIM_IsEnabledExternalClock + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledExternalClock(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->SMCR, TIM_SMCR_ECE) == (TIM_SMCR_ECE)) ? 1UL : 0UL); +} + +/** + * @brief Set the clock source of the counter clock. + * @note when selected clock source is external clock mode 1, the timer input + * the external clock is applied is selected by calling the @ref LL_TIM_SetTriggerInput() + * function. This timer input must be configured by calling + * the @ref LL_TIM_IC_Config() function. + * @note Macro IS_TIM_CLOCKSOURCE_ETRMODE1_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports external clock mode1. + * @note Macro IS_TIM_CLOCKSOURCE_ETRMODE2_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports external clock mode2. + * @rmtoll SMCR SMS LL_TIM_SetClockSource\n + * SMCR ECE LL_TIM_SetClockSource + * @param TIMx Timer instance + * @param ClockSource This parameter can be one of the following values: + * @arg @ref LL_TIM_CLOCKSOURCE_INTERNAL + * @arg @ref LL_TIM_CLOCKSOURCE_EXT_MODE1 + * @arg @ref LL_TIM_CLOCKSOURCE_EXT_MODE2 + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetClockSource(TIM_TypeDef *TIMx, uint32_t ClockSource) +{ + MODIFY_REG(TIMx->SMCR, TIM_SMCR_SMS | TIM_SMCR_ECE, ClockSource); +} + +/** + * @brief Set the encoder interface mode. + * @note Macro IS_TIM_ENCODER_INTERFACE_INSTANCE(TIMx) can be used to check + * whether or not a timer instance supports the encoder mode. + * @rmtoll SMCR SMS LL_TIM_SetEncoderMode + * @param TIMx Timer instance + * @param EncoderMode This parameter can be one of the following values: + * @arg @ref LL_TIM_ENCODERMODE_X2_TI1 + * @arg @ref LL_TIM_ENCODERMODE_X2_TI2 + * @arg @ref LL_TIM_ENCODERMODE_X4_TI12 + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetEncoderMode(TIM_TypeDef *TIMx, uint32_t EncoderMode) +{ + MODIFY_REG(TIMx->SMCR, TIM_SMCR_SMS, EncoderMode); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Timer_Synchronization Timer synchronisation configuration + * @{ + */ +/** + * @brief Set the trigger output (TRGO) used for timer synchronization . + * @note Macro IS_TIM_MASTER_INSTANCE(TIMx) can be used to check + * whether or not a timer instance can operate as a master timer. + * @rmtoll CR2 MMS LL_TIM_SetTriggerOutput + * @param TIMx Timer instance + * @param TimerSynchronization This parameter can be one of the following values: + * @arg @ref LL_TIM_TRGO_RESET + * @arg @ref LL_TIM_TRGO_ENABLE + * @arg @ref LL_TIM_TRGO_UPDATE + * @arg @ref LL_TIM_TRGO_CC1IF + * @arg @ref LL_TIM_TRGO_OC1REF + * @arg @ref LL_TIM_TRGO_OC2REF + * @arg @ref LL_TIM_TRGO_OC3REF + * @arg @ref LL_TIM_TRGO_OC4REF + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetTriggerOutput(TIM_TypeDef *TIMx, uint32_t TimerSynchronization) +{ + MODIFY_REG(TIMx->CR2, TIM_CR2_MMS, TimerSynchronization); +} + +/** + * @brief Set the trigger output 2 (TRGO2) used for ADC synchronization . + * @note Macro IS_TIM_TRGO2_INSTANCE(TIMx) can be used to check + * whether or not a timer instance can be used for ADC synchronization. + * @rmtoll CR2 MMS2 LL_TIM_SetTriggerOutput2 + * @param TIMx Timer Instance + * @param ADCSynchronization This parameter can be one of the following values: + * @arg @ref LL_TIM_TRGO2_RESET + * @arg @ref LL_TIM_TRGO2_ENABLE + * @arg @ref LL_TIM_TRGO2_UPDATE + * @arg @ref LL_TIM_TRGO2_CC1F + * @arg @ref LL_TIM_TRGO2_OC1 + * @arg @ref LL_TIM_TRGO2_OC2 + * @arg @ref LL_TIM_TRGO2_OC3 + * @arg @ref LL_TIM_TRGO2_OC4 + * @arg @ref LL_TIM_TRGO2_OC5 + * @arg @ref LL_TIM_TRGO2_OC6 + * @arg @ref LL_TIM_TRGO2_OC4_RISINGFALLING + * @arg @ref LL_TIM_TRGO2_OC6_RISINGFALLING + * @arg @ref LL_TIM_TRGO2_OC4_RISING_OC6_RISING + * @arg @ref LL_TIM_TRGO2_OC4_RISING_OC6_FALLING + * @arg @ref LL_TIM_TRGO2_OC5_RISING_OC6_RISING + * @arg @ref LL_TIM_TRGO2_OC5_RISING_OC6_FALLING + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetTriggerOutput2(TIM_TypeDef *TIMx, uint32_t ADCSynchronization) +{ + MODIFY_REG(TIMx->CR2, TIM_CR2_MMS2, ADCSynchronization); +} + +/** + * @brief Set the synchronization mode of a slave timer. + * @note Macro IS_TIM_SLAVE_INSTANCE(TIMx) can be used to check whether or not + * a timer instance can operate as a slave timer. + * @rmtoll SMCR SMS LL_TIM_SetSlaveMode + * @param TIMx Timer instance + * @param SlaveMode This parameter can be one of the following values: + * @arg @ref LL_TIM_SLAVEMODE_DISABLED + * @arg @ref LL_TIM_SLAVEMODE_RESET + * @arg @ref LL_TIM_SLAVEMODE_GATED + * @arg @ref LL_TIM_SLAVEMODE_TRIGGER + * @arg @ref LL_TIM_SLAVEMODE_COMBINED_RESETTRIGGER + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetSlaveMode(TIM_TypeDef *TIMx, uint32_t SlaveMode) +{ + MODIFY_REG(TIMx->SMCR, TIM_SMCR_SMS, SlaveMode); +} + +/** + * @brief Set the selects the trigger input to be used to synchronize the counter. + * @note Macro IS_TIM_SLAVE_INSTANCE(TIMx) can be used to check whether or not + * a timer instance can operate as a slave timer. + * @rmtoll SMCR TS LL_TIM_SetTriggerInput + * @param TIMx Timer instance + * @param TriggerInput This parameter can be one of the following values: + * @arg @ref LL_TIM_TS_ITR0 + * @arg @ref LL_TIM_TS_ITR1 + * @arg @ref LL_TIM_TS_ITR2 + * @arg @ref LL_TIM_TS_ITR3 + * @arg @ref LL_TIM_TS_TI1F_ED + * @arg @ref LL_TIM_TS_TI1FP1 + * @arg @ref LL_TIM_TS_TI2FP2 + * @arg @ref LL_TIM_TS_ETRF + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetTriggerInput(TIM_TypeDef *TIMx, uint32_t TriggerInput) +{ + MODIFY_REG(TIMx->SMCR, TIM_SMCR_TS, TriggerInput); +} + +/** + * @brief Enable the Master/Slave mode. + * @note Macro IS_TIM_SLAVE_INSTANCE(TIMx) can be used to check whether or not + * a timer instance can operate as a slave timer. + * @rmtoll SMCR MSM LL_TIM_EnableMasterSlaveMode + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableMasterSlaveMode(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->SMCR, TIM_SMCR_MSM); +} + +/** + * @brief Disable the Master/Slave mode. + * @note Macro IS_TIM_SLAVE_INSTANCE(TIMx) can be used to check whether or not + * a timer instance can operate as a slave timer. + * @rmtoll SMCR MSM LL_TIM_DisableMasterSlaveMode + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableMasterSlaveMode(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->SMCR, TIM_SMCR_MSM); +} + +/** + * @brief Indicates whether the Master/Slave mode is enabled. + * @note Macro IS_TIM_SLAVE_INSTANCE(TIMx) can be used to check whether or not + * a timer instance can operate as a slave timer. + * @rmtoll SMCR MSM LL_TIM_IsEnabledMasterSlaveMode + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledMasterSlaveMode(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->SMCR, TIM_SMCR_MSM) == (TIM_SMCR_MSM)) ? 1UL : 0UL); +} + +/** + * @brief Configure the external trigger (ETR) input. + * @note Macro IS_TIM_ETR_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides an external trigger input. + * @rmtoll SMCR ETP LL_TIM_ConfigETR\n + * SMCR ETPS LL_TIM_ConfigETR\n + * SMCR ETF LL_TIM_ConfigETR + * @param TIMx Timer instance + * @param ETRPolarity This parameter can be one of the following values: + * @arg @ref LL_TIM_ETR_POLARITY_NONINVERTED + * @arg @ref LL_TIM_ETR_POLARITY_INVERTED + * @param ETRPrescaler This parameter can be one of the following values: + * @arg @ref LL_TIM_ETR_PRESCALER_DIV1 + * @arg @ref LL_TIM_ETR_PRESCALER_DIV2 + * @arg @ref LL_TIM_ETR_PRESCALER_DIV4 + * @arg @ref LL_TIM_ETR_PRESCALER_DIV8 + * @param ETRFilter This parameter can be one of the following values: + * @arg @ref LL_TIM_ETR_FILTER_FDIV1 + * @arg @ref LL_TIM_ETR_FILTER_FDIV1_N2 + * @arg @ref LL_TIM_ETR_FILTER_FDIV1_N4 + * @arg @ref LL_TIM_ETR_FILTER_FDIV1_N8 + * @arg @ref LL_TIM_ETR_FILTER_FDIV2_N6 + * @arg @ref LL_TIM_ETR_FILTER_FDIV2_N8 + * @arg @ref LL_TIM_ETR_FILTER_FDIV4_N6 + * @arg @ref LL_TIM_ETR_FILTER_FDIV4_N8 + * @arg @ref LL_TIM_ETR_FILTER_FDIV8_N6 + * @arg @ref LL_TIM_ETR_FILTER_FDIV8_N8 + * @arg @ref LL_TIM_ETR_FILTER_FDIV16_N5 + * @arg @ref LL_TIM_ETR_FILTER_FDIV16_N6 + * @arg @ref LL_TIM_ETR_FILTER_FDIV16_N8 + * @arg @ref LL_TIM_ETR_FILTER_FDIV32_N5 + * @arg @ref LL_TIM_ETR_FILTER_FDIV32_N6 + * @arg @ref LL_TIM_ETR_FILTER_FDIV32_N8 + * @retval None + */ +__STATIC_INLINE void LL_TIM_ConfigETR(TIM_TypeDef *TIMx, uint32_t ETRPolarity, uint32_t ETRPrescaler, + uint32_t ETRFilter) +{ + MODIFY_REG(TIMx->SMCR, TIM_SMCR_ETP | TIM_SMCR_ETPS | TIM_SMCR_ETF, ETRPolarity | ETRPrescaler | ETRFilter); +} + +/** + * @brief Select the external trigger (ETR) input source. + * @note Macro IS_TIM_ETRSEL_INSTANCE(TIMx) can be used to check whether or + * not a timer instance supports ETR source selection. + * @rmtoll OR2 ETRSEL LL_TIM_SetETRSource + * @param TIMx Timer instance + * @param ETRSource This parameter can be one of the following values: + * @arg @ref LL_TIM_ETRSOURCE_LEGACY + * @arg @ref LL_TIM_ETRSOURCE_COMP1 + * @arg @ref LL_TIM_ETRSOURCE_COMP2 + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetETRSource(TIM_TypeDef *TIMx, uint32_t ETRSource) +{ + MODIFY_REG(TIMx->OR2, TIMx_OR2_ETRSEL, ETRSource); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Break_Function Break function configuration + * @{ + */ +/** + * @brief Enable the break function. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR BKE LL_TIM_EnableBRK + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableBRK(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->BDTR, TIM_BDTR_BKE); +} + +/** + * @brief Disable the break function. + * @rmtoll BDTR BKE LL_TIM_DisableBRK + * @param TIMx Timer instance + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableBRK(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->BDTR, TIM_BDTR_BKE); +} + +/** + * @brief Configure the break input. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR BKP LL_TIM_ConfigBRK\n + * BDTR BKF LL_TIM_ConfigBRK + * @param TIMx Timer instance + * @param BreakPolarity This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK_POLARITY_LOW + * @arg @ref LL_TIM_BREAK_POLARITY_HIGH + * @param BreakFilter This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK_FILTER_FDIV1 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV1_N2 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV1_N4 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV1_N8 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV2_N6 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV2_N8 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV4_N6 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV4_N8 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV8_N6 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV8_N8 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV16_N5 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV16_N6 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV16_N8 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV32_N5 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV32_N6 + * @arg @ref LL_TIM_BREAK_FILTER_FDIV32_N8 + * @retval None + */ +__STATIC_INLINE void LL_TIM_ConfigBRK(TIM_TypeDef *TIMx, uint32_t BreakPolarity, + uint32_t BreakFilter) +{ + MODIFY_REG(TIMx->BDTR, TIM_BDTR_BKP | TIM_BDTR_BKF, BreakPolarity | BreakFilter); +} + +/** + * @brief Enable the break 2 function. + * @note Macro IS_TIM_BKIN2_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a second break input. + * @rmtoll BDTR BK2E LL_TIM_EnableBRK2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableBRK2(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->BDTR, TIM_BDTR_BK2E); +} + +/** + * @brief Disable the break 2 function. + * @note Macro IS_TIM_BKIN2_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a second break input. + * @rmtoll BDTR BK2E LL_TIM_DisableBRK2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableBRK2(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->BDTR, TIM_BDTR_BK2E); +} + +/** + * @brief Configure the break 2 input. + * @note Macro IS_TIM_BKIN2_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a second break input. + * @rmtoll BDTR BK2P LL_TIM_ConfigBRK2\n + * BDTR BK2F LL_TIM_ConfigBRK2 + * @param TIMx Timer instance + * @param Break2Polarity This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK2_POLARITY_LOW + * @arg @ref LL_TIM_BREAK2_POLARITY_HIGH + * @param Break2Filter This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV1 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV1_N2 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV1_N4 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV1_N8 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV2_N6 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV2_N8 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV4_N6 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV4_N8 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV8_N6 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV8_N8 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV16_N5 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV16_N6 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV16_N8 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV32_N5 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV32_N6 + * @arg @ref LL_TIM_BREAK2_FILTER_FDIV32_N8 + * @retval None + */ +__STATIC_INLINE void LL_TIM_ConfigBRK2(TIM_TypeDef *TIMx, uint32_t Break2Polarity, uint32_t Break2Filter) +{ + MODIFY_REG(TIMx->BDTR, TIM_BDTR_BK2P | TIM_BDTR_BK2F, Break2Polarity | Break2Filter); +} + +/** + * @brief Select the outputs off state (enabled v.s. disabled) in Idle and Run modes. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR OSSI LL_TIM_SetOffStates\n + * BDTR OSSR LL_TIM_SetOffStates + * @param TIMx Timer instance + * @param OffStateIdle This parameter can be one of the following values: + * @arg @ref LL_TIM_OSSI_DISABLE + * @arg @ref LL_TIM_OSSI_ENABLE + * @param OffStateRun This parameter can be one of the following values: + * @arg @ref LL_TIM_OSSR_DISABLE + * @arg @ref LL_TIM_OSSR_ENABLE + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetOffStates(TIM_TypeDef *TIMx, uint32_t OffStateIdle, uint32_t OffStateRun) +{ + MODIFY_REG(TIMx->BDTR, TIM_BDTR_OSSI | TIM_BDTR_OSSR, OffStateIdle | OffStateRun); +} + +/** + * @brief Enable automatic output (MOE can be set by software or automatically when a break input is active). + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR AOE LL_TIM_EnableAutomaticOutput + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableAutomaticOutput(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->BDTR, TIM_BDTR_AOE); +} + +/** + * @brief Disable automatic output (MOE can be set only by software). + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR AOE LL_TIM_DisableAutomaticOutput + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableAutomaticOutput(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->BDTR, TIM_BDTR_AOE); +} + +/** + * @brief Indicate whether automatic output is enabled. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR AOE LL_TIM_IsEnabledAutomaticOutput + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledAutomaticOutput(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->BDTR, TIM_BDTR_AOE) == (TIM_BDTR_AOE)) ? 1UL : 0UL); +} + +/** + * @brief Enable the outputs (set the MOE bit in TIMx_BDTR register). + * @note The MOE bit in TIMx_BDTR register allows to enable /disable the outputs by + * software and is reset in case of break or break2 event + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR MOE LL_TIM_EnableAllOutputs + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableAllOutputs(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->BDTR, TIM_BDTR_MOE); +} + +/** + * @brief Disable the outputs (reset the MOE bit in TIMx_BDTR register). + * @note The MOE bit in TIMx_BDTR register allows to enable /disable the outputs by + * software and is reset in case of break or break2 event. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR MOE LL_TIM_DisableAllOutputs + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableAllOutputs(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->BDTR, TIM_BDTR_MOE); +} + +/** + * @brief Indicates whether outputs are enabled. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @rmtoll BDTR MOE LL_TIM_IsEnabledAllOutputs + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsEnabledAllOutputs(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->BDTR, TIM_BDTR_MOE) == (TIM_BDTR_MOE)) ? 1UL : 0UL); +} + +/** + * @brief Enable the signals connected to the designated timer break input. + * @note Macro IS_TIM_BREAKSOURCE_INSTANCE(TIMx) can be used to check whether + * or not a timer instance allows for break input selection. + * @rmtoll OR2 BKINE LL_TIM_EnableBreakInputSource\n + * OR2 BKCMP1E LL_TIM_EnableBreakInputSource\n + * OR2 BKCMP2E LL_TIM_EnableBreakInputSource\n + * OR2 BKDF1BK0E LL_TIM_EnableBreakInputSource\n + * OR3 BK2INE LL_TIM_EnableBreakInputSource\n + * OR3 BK2CMP1E LL_TIM_EnableBreakInputSource\n + * OR3 BK2CMP2E LL_TIM_EnableBreakInputSource\n + * OR3 BK2DF1BK1E LL_TIM_EnableBreakInputSource + * @param TIMx Timer instance + * @param BreakInput This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK_INPUT_BKIN + * @arg @ref LL_TIM_BREAK_INPUT_BKIN2 + * @param Source This parameter can be one of the following values: + * @arg @ref LL_TIM_BKIN_SOURCE_BKIN + * @arg @ref LL_TIM_BKIN_SOURCE_BKCOMP1 + * @arg @ref LL_TIM_BKIN_SOURCE_BKCOMP2 + * @arg @ref LL_TIM_BKIN_SOURCE_DF1BK + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableBreakInputSource(TIM_TypeDef *TIMx, uint32_t BreakInput, uint32_t Source) +{ + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->OR2) + BreakInput)); + SET_BIT(*pReg, Source); +} + +/** + * @brief Disable the signals connected to the designated timer break input. + * @note Macro IS_TIM_BREAKSOURCE_INSTANCE(TIMx) can be used to check whether + * or not a timer instance allows for break input selection. + * @rmtoll OR2 BKINE LL_TIM_DisableBreakInputSource\n + * OR2 BKCMP1E LL_TIM_DisableBreakInputSource\n + * OR2 BKCMP2E LL_TIM_DisableBreakInputSource\n + * OR2 BKDF1BK0E LL_TIM_DisableBreakInputSource\n + * OR3 BK2INE LL_TIM_DisableBreakInputSource\n + * OR3 BK2CMP1E LL_TIM_DisableBreakInputSource\n + * OR3 BK2CMP2E LL_TIM_DisableBreakInputSource\n + * OR3 BK2DF1BK1E LL_TIM_DisableBreakInputSource + * @param TIMx Timer instance + * @param BreakInput This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK_INPUT_BKIN + * @arg @ref LL_TIM_BREAK_INPUT_BKIN2 + * @param Source This parameter can be one of the following values: + * @arg @ref LL_TIM_BKIN_SOURCE_BKIN + * @arg @ref LL_TIM_BKIN_SOURCE_BKCOMP1 + * @arg @ref LL_TIM_BKIN_SOURCE_BKCOMP2 + * @arg @ref LL_TIM_BKIN_SOURCE_DF1BK + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableBreakInputSource(TIM_TypeDef *TIMx, uint32_t BreakInput, uint32_t Source) +{ + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->OR2) + BreakInput)); + CLEAR_BIT(*pReg, Source); +} + +/** + * @brief Set the polarity of the break signal for the timer break input. + * @note Macro IS_TIM_BREAKSOURCE_INSTANCE(TIMx) can be used to check whether + * or not a timer instance allows for break input selection. + * @rmtoll OR2 BKINP LL_TIM_SetBreakInputSourcePolarity\n + * OR2 BKCMP1P LL_TIM_SetBreakInputSourcePolarity\n + * OR2 BKCMP2P LL_TIM_SetBreakInputSourcePolarity\n + * OR3 BK2INP LL_TIM_SetBreakInputSourcePolarity\n + * OR3 BK2CMP1P LL_TIM_SetBreakInputSourcePolarity\n + * OR3 BK2CMP2P LL_TIM_SetBreakInputSourcePolarity + * @param TIMx Timer instance + * @param BreakInput This parameter can be one of the following values: + * @arg @ref LL_TIM_BREAK_INPUT_BKIN + * @arg @ref LL_TIM_BREAK_INPUT_BKIN2 + * @param Source This parameter can be one of the following values: + * @arg @ref LL_TIM_BKIN_SOURCE_BKIN + * @arg @ref LL_TIM_BKIN_SOURCE_BKCOMP1 + * @arg @ref LL_TIM_BKIN_SOURCE_BKCOMP2 + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_TIM_BKIN_POLARITY_LOW + * @arg @ref LL_TIM_BKIN_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetBreakInputSourcePolarity(TIM_TypeDef *TIMx, uint32_t BreakInput, uint32_t Source, + uint32_t Polarity) +{ + __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->OR2) + BreakInput)); + MODIFY_REG(*pReg, (TIMx_OR2_BKINP << TIM_POSITION_BRK_SOURCE), (Polarity << TIM_POSITION_BRK_SOURCE)); +} +/** + * @} + */ + +/** @defgroup TIM_LL_EF_DMA_Burst_Mode DMA burst mode configuration + * @{ + */ +/** + * @brief Configures the timer DMA burst feature. + * @note Macro IS_TIM_DMABURST_INSTANCE(TIMx) can be used to check whether or + * not a timer instance supports the DMA burst mode. + * @rmtoll DCR DBL LL_TIM_ConfigDMABurst\n + * DCR DBA LL_TIM_ConfigDMABurst + * @param TIMx Timer instance + * @param DMABurstBaseAddress This parameter can be one of the following values: + * @arg @ref LL_TIM_DMABURST_BASEADDR_CR1 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CR2 + * @arg @ref LL_TIM_DMABURST_BASEADDR_SMCR + * @arg @ref LL_TIM_DMABURST_BASEADDR_DIER + * @arg @ref LL_TIM_DMABURST_BASEADDR_SR + * @arg @ref LL_TIM_DMABURST_BASEADDR_EGR + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCMR1 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCMR2 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCER + * @arg @ref LL_TIM_DMABURST_BASEADDR_CNT + * @arg @ref LL_TIM_DMABURST_BASEADDR_PSC + * @arg @ref LL_TIM_DMABURST_BASEADDR_ARR + * @arg @ref LL_TIM_DMABURST_BASEADDR_RCR + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCR1 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCR2 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCR3 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCR4 + * @arg @ref LL_TIM_DMABURST_BASEADDR_BDTR + * @arg @ref LL_TIM_DMABURST_BASEADDR_OR1 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCMR3 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCR5 + * @arg @ref LL_TIM_DMABURST_BASEADDR_CCR6 + * @arg @ref LL_TIM_DMABURST_BASEADDR_OR2 + * @arg @ref LL_TIM_DMABURST_BASEADDR_OR3 + * @param DMABurstLength This parameter can be one of the following values: + * @arg @ref LL_TIM_DMABURST_LENGTH_1TRANSFER + * @arg @ref LL_TIM_DMABURST_LENGTH_2TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_3TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_4TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_5TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_6TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_7TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_8TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_9TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_10TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_11TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_12TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_13TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_14TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_15TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_16TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_17TRANSFERS + * @arg @ref LL_TIM_DMABURST_LENGTH_18TRANSFERS + * @retval None + */ +__STATIC_INLINE void LL_TIM_ConfigDMABurst(TIM_TypeDef *TIMx, uint32_t DMABurstBaseAddress, uint32_t DMABurstLength) +{ + MODIFY_REG(TIMx->DCR, (TIM_DCR_DBL | TIM_DCR_DBA), (DMABurstBaseAddress | DMABurstLength)); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_Timer_Inputs_Remapping Timer input remapping + * @{ + */ +/** + * @brief Remap TIM inputs (input channel, internal/external triggers). + * @note Macro IS_TIM_REMAP_INSTANCE(TIMx) can be used to check whether or not + * a some timer inputs can be remapped. + @if STM32L486xx + * @rmtoll TIM1_OR1 ETR_ADC1_RMP LL_TIM_SetRemap\n + * TIM1_OR1 ETR_ADC3_RMP LL_TIM_SetRemap\n + * TIM1_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM8_OR1 ETR_ADC2_RMP LL_TIM_SetRemap\n + * TIM8_OR1 ETR_ADC3_RMP LL_TIM_SetRemap\n + * TIM8_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM2_OR1 ITR1_RMP LL_TIM_SetRemap\n + * TIM2_OR1 TI4_RMP LL_TIM_SetRemap\n + * TIM2_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM3_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM15_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM15_OR1 ENCODER_MODE LL_TIM_SetRemap\n + * TIM16_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM17_OR1 TI1_RMP LL_TIM_SetRemap + @endif + @if STM32L443xx + * @rmtoll TIM1_OR1 ETR_ADC1_RMP LL_TIM_SetRemap\n + * TIM1_OR1 ETR_ADC3_RMP LL_TIM_SetRemap\n + * TIM1_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM2_OR1 ITR1_RMP LL_TIM_SetRemap\n + * TIM2_OR1 TI4_RMP LL_TIM_SetRemap\n + * TIM2_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM15_OR1 TI1_RMP LL_TIM_SetRemap\n + * TIM15_OR1 ENCODER_MODE LL_TIM_SetRemap\n + * TIM16_OR1 TI1_RMP LL_TIM_SetRemap\n + @endif + * @param TIMx Timer instance + * @param Remap Remap param depends on the TIMx. Description available only + * in CHM version of the User Manual (not in .pdf). + * Otherwise see Reference Manual description of OR registers. + * + * Below description summarizes "Timer Instance" and "Remap" param combinations: + * + @if STM32L486xx + * TIM1: any combination of TI1_RMP, ADC3_RMP, ADC1_RMP where + * + * . . ADC1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_NC + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_AWD1 + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_AWD2 + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_AWD3 + * + * . . ADC3_RMP can be one of the following values + * @arg @ref LL_TIM_TIM1_ETR_ADC3_RMP_NC + * @arg @ref LL_TIM_TIM1_ETR_ADC3_RMP_AWD1 + * @arg @ref LL_TIM_TIM1_ETR_ADC3_RMP_AWD2 + * @arg @ref LL_TIM_TIM1_ETR_ADC3_RMP_AWD3 + * + * . . TI1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM1_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM1_TI1_RMP_COMP1 + * + * TIM2: any combination of ITR1_RMP, ETR1_RMP, TI4_RMP where + * + * ITR1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM2_ITR1_RMP_TIM8_TRGO + * @arg @ref LL_TIM_TIM2_ITR1_RMP_OTG_FS_SOF + * + * . . ETR1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM2_ETR_RMP_GPIO + * @arg @ref LL_TIM_TIM2_ETR_RMP_LSE + * + * . . TI4_RMP can be one of the following values + * @arg @ref LL_TIM_TIM2_TI4_RMP_GPIO + * @arg @ref LL_TIM_TIM2_TI4_RMP_COMP1 + * @arg @ref LL_TIM_TIM2_TI4_RMP_COMP2 + * @arg @ref LL_TIM_TIM2_TI4_RMP_COMP1_COMP2 + * + * TIM3: one of the following values + * + * @arg @ref LL_TIM_TIM3_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM3_TI1_RMP_COMP1 + * @arg @ref LL_TIM_TIM3_TI1_RMP_COMP2 + * @arg @ref LL_TIM_TIM3_TI1_RMP_COMP1_COMP2 + * + * TIM8: any combination of TI1_RMP, ADC3_RMP, ADC1_RMP where + * + * . . ADC1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM8_ETR_ADC2_RMP_NC + * @arg @ref LL_TIM_TIM8_ETR_ADC2_RMP_AWD1 + * @arg @ref LL_TIM_TIM8_ETR_ADC2_RMP_AWD2 + * @arg @ref LL_TIM_TIM8_ETR_ADC2_RMP_AWD3 + * + * . . ADC3_RMP can be one of the following values + * @arg @ref LL_TIM_TIM8_ETR_ADC3_RMP_NC + * @arg @ref LL_TIM_TIM8_ETR_ADC3_RMP_AWD1 + * @arg @ref LL_TIM_TIM8_ETR_ADC3_RMP_AWD2 + * @arg @ref LL_TIM_TIM8_ETR_ADC3_RMP_AWD3 + * + * . . TI1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM8_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM8_TI1_RMP_COMP2 + * + * TIM15: any combination of TI1_RMP, ENCODER_MODE where + * + * . . TI1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM15_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM15_TI1_RMP_LSE + * + * . . ENCODER_MODE can be one of the following values + * @arg @ref LL_TIM_TIM15_ENCODERMODE_NOREDIRECTION + * @arg @ref LL_TIM_TIM15_ENCODERMODE_TIM2 + * @arg @ref LL_TIM_TIM15_ENCODERMODE_TIM3 + * @arg @ref LL_TIM_TIM15_ENCODERMODE_TIM4 + * + * TIM16: one of the following values + * + * @arg @ref LL_TIM_TIM16_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM16_TI1_RMP_LSI + * @arg @ref LL_TIM_TIM16_TI1_RMP_LSE + * @arg @ref LL_TIM_TIM16_TI1_RMP_RTC + * @arg @ref LL_TIM_TIM16_TI1_RMP_MSI + * @arg @ref LL_TIM_TIM16_TI1_RMP_HSE_32 + * @arg @ref LL_TIM_TIM16_TI1_RMP_MCO + * + * TIM17: one of the following values + * + * @arg @ref LL_TIM_TIM17_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM17_TI1_RMP_MSI + * @arg @ref LL_TIM_TIM17_TI1_RMP_HSE_32 + * @arg @ref LL_TIM_TIM17_TI1_RMP_MCO + @endif + @if STM32L443xx + * TIM1: any combination of TI1_RMP, ADC3_RMP, ADC1_RMP where + * + * . . ADC1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_NC + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_AWD1 + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_AWD2 + * @arg @ref LL_TIM_TIM1_ETR_ADC1_RMP_AWD3 + * + * . . TI1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM1_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM1_TI1_RMP_COMP1 + * + * TIM2: any combination of ITR1_RMP, ETR1_RMP, TI4_RMP where + * + * ITR1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM2_ITR1_RMP_NONE + * @arg @ref LL_TIM_TIM2_ITR1_RMP_USB_SOF + * + * . . ETR1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM2_ETR_RMP_GPIO + * @arg @ref LL_TIM_TIM2_ETR_RMP_LSE + * + * . . TI4_RMP can be one of the following values + * @arg @ref LL_TIM_TIM2_TI4_RMP_GPIO + * @arg @ref LL_TIM_TIM2_TI4_RMP_COMP1 + * @arg @ref LL_TIM_TIM2_TI4_RMP_COMP2 + * @arg @ref LL_TIM_TIM2_TI4_RMP_COMP1_COMP2 + * + * TIM15: any combination of TI1_RMP, ENCODER_MODE where + * + * . . TI1_RMP can be one of the following values + * @arg @ref LL_TIM_TIM15_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM15_TI1_RMP_LSE + * + * . . ENCODER_MODE can be one of the following values + * @arg @ref LL_TIM_TIM15_ENCODERMODE_NOREDIRECTION + * @arg @ref LL_TIM_TIM15_ENCODERMODE_TIM2 + * @arg @ref LL_TIM_TIM15_ENCODERMODE_TIM3 + * @arg @ref LL_TIM_TIM15_ENCODERMODE_TIM4 + * + * TIM16: one of the following values + * + * @arg @ref LL_TIM_TIM16_TI1_RMP_GPIO + * @arg @ref LL_TIM_TIM16_TI1_RMP_LSI + * @arg @ref LL_TIM_TIM16_TI1_RMP_LSE + * @arg @ref LL_TIM_TIM16_TI1_RMP_RTC + * @arg @ref LL_TIM_TIM16_TI1_RMP_MSI + * @arg @ref LL_TIM_TIM16_TI1_RMP_HSE_32 + * @arg @ref LL_TIM_TIM16_TI1_RMP_MCO + @endif + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetRemap(TIM_TypeDef *TIMx, uint32_t Remap) +{ + MODIFY_REG(TIMx->OR1, (Remap >> TIMx_OR1_RMP_SHIFT), (Remap & TIMx_OR1_RMP_MASK)); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_OCREF_Clear OCREF_Clear_Management + * @{ + */ +/** + * @brief Set the OCREF clear input source + * @note The OCxREF signal of a given channel can be cleared when a high level is applied on the OCREF_CLR_INPUT + * @note This function can only be used in Output compare and PWM modes. + * @rmtoll SMCR OCCS LL_TIM_SetOCRefClearInputSource + * @param TIMx Timer instance + * @param OCRefClearInputSource This parameter can be one of the following values: + * @arg @ref LL_TIM_OCREF_CLR_INT_NC + * @arg @ref LL_TIM_OCREF_CLR_INT_ETR + * @retval None + */ +__STATIC_INLINE void LL_TIM_SetOCRefClearInputSource(TIM_TypeDef *TIMx, uint32_t OCRefClearInputSource) +{ + MODIFY_REG(TIMx->SMCR, TIM_SMCR_OCCS, OCRefClearInputSource); +} +/** + * @} + */ + +/** @defgroup TIM_LL_EF_FLAG_Management FLAG-Management + * @{ + */ +/** + * @brief Clear the update interrupt flag (UIF). + * @rmtoll SR UIF LL_TIM_ClearFlag_UPDATE + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_UPDATE(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_UIF)); +} + +/** + * @brief Indicate whether update interrupt flag (UIF) is set (update interrupt is pending). + * @rmtoll SR UIF LL_TIM_IsActiveFlag_UPDATE + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 1 interrupt flag (CC1F). + * @rmtoll SR CC1IF LL_TIM_ClearFlag_CC1 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC1(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC1IF)); +} + +/** + * @brief Indicate whether Capture/Compare 1 interrupt flag (CC1F) is set (Capture/Compare 1 interrupt is pending). + * @rmtoll SR CC1IF LL_TIM_IsActiveFlag_CC1 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 2 interrupt flag (CC2F). + * @rmtoll SR CC2IF LL_TIM_ClearFlag_CC2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC2(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC2IF)); +} + +/** + * @brief Indicate whether Capture/Compare 2 interrupt flag (CC2F) is set (Capture/Compare 2 interrupt is pending). + * @rmtoll SR CC2IF LL_TIM_IsActiveFlag_CC2 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 3 interrupt flag (CC3F). + * @rmtoll SR CC3IF LL_TIM_ClearFlag_CC3 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC3(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC3IF)); +} + +/** + * @brief Indicate whether Capture/Compare 3 interrupt flag (CC3F) is set (Capture/Compare 3 interrupt is pending). + * @rmtoll SR CC3IF LL_TIM_IsActiveFlag_CC3 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 4 interrupt flag (CC4F). + * @rmtoll SR CC4IF LL_TIM_ClearFlag_CC4 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC4(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC4IF)); +} + +/** + * @brief Indicate whether Capture/Compare 4 interrupt flag (CC4F) is set (Capture/Compare 4 interrupt is pending). + * @rmtoll SR CC4IF LL_TIM_IsActiveFlag_CC4 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 5 interrupt flag (CC5F). + * @rmtoll SR CC5IF LL_TIM_ClearFlag_CC5 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC5(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC5IF)); +} + +/** + * @brief Indicate whether Capture/Compare 5 interrupt flag (CC5F) is set (Capture/Compare 5 interrupt is pending). + * @rmtoll SR CC5IF LL_TIM_IsActiveFlag_CC5 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC5(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->SR, TIM_SR_CC5IF) == (TIM_SR_CC5IF)) ? 1UL : 0UL); +} + +/** + * @brief Clear the Capture/Compare 6 interrupt flag (CC6F). + * @rmtoll SR CC6IF LL_TIM_ClearFlag_CC6 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC6(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC6IF)); +} + +/** + * @brief Indicate whether Capture/Compare 6 interrupt flag (CC6F) is set (Capture/Compare 6 interrupt is pending). + * @rmtoll SR CC6IF LL_TIM_IsActiveFlag_CC6 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC6(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->SR, TIM_SR_CC6IF) == (TIM_SR_CC6IF)) ? 1UL : 0UL); +} + +/** + * @brief Clear the commutation interrupt flag (COMIF). + * @rmtoll SR COMIF LL_TIM_ClearFlag_COM + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_COM(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_COMIF)); +} + +/** + * @brief Indicate whether commutation interrupt flag (COMIF) is set (commutation interrupt is pending). + * @rmtoll SR COMIF LL_TIM_IsActiveFlag_COM + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the trigger interrupt flag (TIF). + * @rmtoll SR TIF LL_TIM_ClearFlag_TRIG + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_TRIG(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_TIF)); +} + +/** + * @brief Indicate whether trigger interrupt flag (TIF) is set (trigger interrupt is pending). + * @rmtoll SR TIF LL_TIM_IsActiveFlag_TRIG + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the break interrupt flag (BIF). + * @rmtoll SR BIF LL_TIM_ClearFlag_BRK + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_BRK(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_BIF)); +} + +/** + * @brief Indicate whether break interrupt flag (BIF) is set (break interrupt is pending). + * @rmtoll SR BIF LL_TIM_IsActiveFlag_BRK + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the break 2 interrupt flag (B2IF). + * @rmtoll SR B2IF LL_TIM_ClearFlag_BRK2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_BRK2(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_B2IF)); +} + +/** + * @brief Indicate whether break 2 interrupt flag (B2IF) is set (break 2 interrupt is pending). + * @rmtoll SR B2IF LL_TIM_IsActiveFlag_BRK2 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_BRK2(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->SR, TIM_SR_B2IF) == (TIM_SR_B2IF)) ? 1UL : 0UL); +} + +/** + * @brief Clear the Capture/Compare 1 over-capture interrupt flag (CC1OF). + * @rmtoll SR CC1OF LL_TIM_ClearFlag_CC1OVR + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC1OVR(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC1OF)); +} + +/** + * @brief Indicate whether Capture/Compare 1 over-capture interrupt flag (CC1OF) is set + * (Capture/Compare 1 interrupt is pending). + * @rmtoll SR CC1OF LL_TIM_IsActiveFlag_CC1OVR + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 2 over-capture interrupt flag (CC2OF). + * @rmtoll SR CC2OF LL_TIM_ClearFlag_CC2OVR + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC2OVR(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC2OF)); +} + +/** + * @brief Indicate whether Capture/Compare 2 over-capture interrupt flag (CC2OF) is set + * (Capture/Compare 2 over-capture interrupt is pending). + * @rmtoll SR CC2OF LL_TIM_IsActiveFlag_CC2OVR + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 3 over-capture interrupt flag (CC3OF). + * @rmtoll SR CC3OF LL_TIM_ClearFlag_CC3OVR + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC3OVR(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC3OF)); +} + +/** + * @brief Indicate whether Capture/Compare 3 over-capture interrupt flag (CC3OF) is set + * (Capture/Compare 3 over-capture interrupt is pending). + * @rmtoll SR CC3OF LL_TIM_IsActiveFlag_CC3OVR + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the Capture/Compare 4 over-capture interrupt flag (CC4OF). + * @rmtoll SR CC4OF LL_TIM_ClearFlag_CC4OVR + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_CC4OVR(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_CC4OF)); +} + +/** + * @brief Indicate whether Capture/Compare 4 over-capture interrupt flag (CC4OF) is set + * (Capture/Compare 4 over-capture interrupt is pending). + * @rmtoll SR CC4OF LL_TIM_IsActiveFlag_CC4OVR + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Clear the system break interrupt flag (SBIF). + * @rmtoll SR SBIF LL_TIM_ClearFlag_SYSBRK + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_ClearFlag_SYSBRK(TIM_TypeDef *TIMx) +{ + WRITE_REG(TIMx->SR, ~(TIM_SR_SBIF)); +} + +/** + * @brief Indicate whether system break interrupt flag (SBIF) is set (system break interrupt is pending). + * @rmtoll SR SBIF LL_TIM_IsActiveFlag_SYSBRK + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_SYSBRK(const TIM_TypeDef *TIMx) +{ + return ((READ_BIT(TIMx->SR, TIM_SR_SBIF) == (TIM_SR_SBIF)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_IT_Management IT-Management + * @{ + */ +/** + * @brief Enable update interrupt (UIE). + * @rmtoll DIER UIE LL_TIM_EnableIT_UPDATE + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_UPDATE(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_UIE); +} + +/** + * @brief Disable update interrupt (UIE). + * @rmtoll DIER UIE LL_TIM_DisableIT_UPDATE + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_UPDATE(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_UIE); +} + +/** + * @brief Indicates whether the update interrupt (UIE) is enabled. + * @rmtoll DIER UIE LL_TIM_IsEnabledIT_UPDATE + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 1 interrupt (CC1IE). + * @rmtoll DIER CC1IE LL_TIM_EnableIT_CC1 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_CC1(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC1IE); +} + +/** + * @brief Disable capture/compare 1 interrupt (CC1IE). + * @rmtoll DIER CC1IE LL_TIM_DisableIT_CC1 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_CC1(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC1IE); +} + +/** + * @brief Indicates whether the capture/compare 1 interrupt (CC1IE) is enabled. + * @rmtoll DIER CC1IE LL_TIM_IsEnabledIT_CC1 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 2 interrupt (CC2IE). + * @rmtoll DIER CC2IE LL_TIM_EnableIT_CC2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_CC2(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC2IE); +} + +/** + * @brief Disable capture/compare 2 interrupt (CC2IE). + * @rmtoll DIER CC2IE LL_TIM_DisableIT_CC2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_CC2(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC2IE); +} + +/** + * @brief Indicates whether the capture/compare 2 interrupt (CC2IE) is enabled. + * @rmtoll DIER CC2IE LL_TIM_IsEnabledIT_CC2 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 3 interrupt (CC3IE). + * @rmtoll DIER CC3IE LL_TIM_EnableIT_CC3 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_CC3(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC3IE); +} + +/** + * @brief Disable capture/compare 3 interrupt (CC3IE). + * @rmtoll DIER CC3IE LL_TIM_DisableIT_CC3 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_CC3(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC3IE); +} + +/** + * @brief Indicates whether the capture/compare 3 interrupt (CC3IE) is enabled. + * @rmtoll DIER CC3IE LL_TIM_IsEnabledIT_CC3 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 4 interrupt (CC4IE). + * @rmtoll DIER CC4IE LL_TIM_EnableIT_CC4 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_CC4(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC4IE); +} + +/** + * @brief Disable capture/compare 4 interrupt (CC4IE). + * @rmtoll DIER CC4IE LL_TIM_DisableIT_CC4 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_CC4(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC4IE); +} + +/** + * @brief Indicates whether the capture/compare 4 interrupt (CC4IE) is enabled. + * @rmtoll DIER CC4IE LL_TIM_IsEnabledIT_CC4 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable commutation interrupt (COMIE). + * @rmtoll DIER COMIE LL_TIM_EnableIT_COM + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_COM(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_COMIE); +} + +/** + * @brief Disable commutation interrupt (COMIE). + * @rmtoll DIER COMIE LL_TIM_DisableIT_COM + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_COM(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_COMIE); +} + +/** + * @brief Indicates whether the commutation interrupt (COMIE) is enabled. + * @rmtoll DIER COMIE LL_TIM_IsEnabledIT_COM + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable trigger interrupt (TIE). + * @rmtoll DIER TIE LL_TIM_EnableIT_TRIG + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_TRIG(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_TIE); +} + +/** + * @brief Disable trigger interrupt (TIE). + * @rmtoll DIER TIE LL_TIM_DisableIT_TRIG + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_TRIG(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_TIE); +} + +/** + * @brief Indicates whether the trigger interrupt (TIE) is enabled. + * @rmtoll DIER TIE LL_TIM_IsEnabledIT_TRIG + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable break interrupt (BIE). + * @rmtoll DIER BIE LL_TIM_EnableIT_BRK + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableIT_BRK(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_BIE); +} + +/** + * @brief Disable break interrupt (BIE). + * @rmtoll DIER BIE LL_TIM_DisableIT_BRK + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableIT_BRK(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_BIE); +} + +/** + * @brief Indicates whether the break interrupt (BIE) is enabled. + * @rmtoll DIER BIE LL_TIM_IsEnabledIT_BRK + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_DMA_Management DMA Management + * @{ + */ +/** + * @brief Enable update DMA request (UDE). + * @rmtoll DIER UDE LL_TIM_EnableDMAReq_UPDATE + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_UPDATE(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_UDE); +} + +/** + * @brief Disable update DMA request (UDE). + * @rmtoll DIER UDE LL_TIM_DisableDMAReq_UPDATE + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_UPDATE(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_UDE); +} + +/** + * @brief Indicates whether the update DMA request (UDE) is enabled. + * @rmtoll DIER UDE LL_TIM_IsEnabledDMAReq_UPDATE + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 1 DMA request (CC1DE). + * @rmtoll DIER CC1DE LL_TIM_EnableDMAReq_CC1 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_CC1(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC1DE); +} + +/** + * @brief Disable capture/compare 1 DMA request (CC1DE). + * @rmtoll DIER CC1DE LL_TIM_DisableDMAReq_CC1 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_CC1(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC1DE); +} + +/** + * @brief Indicates whether the capture/compare 1 DMA request (CC1DE) is enabled. + * @rmtoll DIER CC1DE LL_TIM_IsEnabledDMAReq_CC1 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 2 DMA request (CC2DE). + * @rmtoll DIER CC2DE LL_TIM_EnableDMAReq_CC2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_CC2(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC2DE); +} + +/** + * @brief Disable capture/compare 2 DMA request (CC2DE). + * @rmtoll DIER CC2DE LL_TIM_DisableDMAReq_CC2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_CC2(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC2DE); +} + +/** + * @brief Indicates whether the capture/compare 2 DMA request (CC2DE) is enabled. + * @rmtoll DIER CC2DE LL_TIM_IsEnabledDMAReq_CC2 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 3 DMA request (CC3DE). + * @rmtoll DIER CC3DE LL_TIM_EnableDMAReq_CC3 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_CC3(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC3DE); +} + +/** + * @brief Disable capture/compare 3 DMA request (CC3DE). + * @rmtoll DIER CC3DE LL_TIM_DisableDMAReq_CC3 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_CC3(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC3DE); +} + +/** + * @brief Indicates whether the capture/compare 3 DMA request (CC3DE) is enabled. + * @rmtoll DIER CC3DE LL_TIM_IsEnabledDMAReq_CC3 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable capture/compare 4 DMA request (CC4DE). + * @rmtoll DIER CC4DE LL_TIM_EnableDMAReq_CC4 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_CC4(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_CC4DE); +} + +/** + * @brief Disable capture/compare 4 DMA request (CC4DE). + * @rmtoll DIER CC4DE LL_TIM_DisableDMAReq_CC4 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_CC4(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_CC4DE); +} + +/** + * @brief Indicates whether the capture/compare 4 DMA request (CC4DE) is enabled. + * @rmtoll DIER CC4DE LL_TIM_IsEnabledDMAReq_CC4 + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable commutation DMA request (COMDE). + * @rmtoll DIER COMDE LL_TIM_EnableDMAReq_COM + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_COM(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_COMDE); +} + +/** + * @brief Disable commutation DMA request (COMDE). + * @rmtoll DIER COMDE LL_TIM_DisableDMAReq_COM + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_COM(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_COMDE); +} + +/** + * @brief Indicates whether the commutation DMA request (COMDE) is enabled. + * @rmtoll DIER COMDE LL_TIM_IsEnabledDMAReq_COM + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @brief Enable trigger interrupt (TDE). + * @rmtoll DIER TDE LL_TIM_EnableDMAReq_TRIG + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_EnableDMAReq_TRIG(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->DIER, TIM_DIER_TDE); +} + +/** + * @brief Disable trigger interrupt (TDE). + * @rmtoll DIER TDE LL_TIM_DisableDMAReq_TRIG + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_DisableDMAReq_TRIG(TIM_TypeDef *TIMx) +{ + CLEAR_BIT(TIMx->DIER, TIM_DIER_TDE); +} + +/** + * @brief Indicates whether the trigger interrupt (TDE) is enabled. + * @rmtoll DIER TDE LL_TIM_IsEnabledDMAReq_TRIG + * @param TIMx Timer instance + * @retval State of bit (1 or 0). + */ +__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); +} + +/** + * @} + */ + +/** @defgroup TIM_LL_EF_EVENT_Management EVENT-Management + * @{ + */ +/** + * @brief Generate an update event. + * @rmtoll EGR UG LL_TIM_GenerateEvent_UPDATE + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_UPDATE(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_UG); +} + +/** + * @brief Generate Capture/Compare 1 event. + * @rmtoll EGR CC1G LL_TIM_GenerateEvent_CC1 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_CC1(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_CC1G); +} + +/** + * @brief Generate Capture/Compare 2 event. + * @rmtoll EGR CC2G LL_TIM_GenerateEvent_CC2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_CC2(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_CC2G); +} + +/** + * @brief Generate Capture/Compare 3 event. + * @rmtoll EGR CC3G LL_TIM_GenerateEvent_CC3 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_CC3(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_CC3G); +} + +/** + * @brief Generate Capture/Compare 4 event. + * @rmtoll EGR CC4G LL_TIM_GenerateEvent_CC4 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_CC4(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_CC4G); +} + +/** + * @brief Generate commutation event. + * @rmtoll EGR COMG LL_TIM_GenerateEvent_COM + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_COM(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_COMG); +} + +/** + * @brief Generate trigger event. + * @rmtoll EGR TG LL_TIM_GenerateEvent_TRIG + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_TRIG(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_TG); +} + +/** + * @brief Generate break event. + * @rmtoll EGR BG LL_TIM_GenerateEvent_BRK + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_BRK(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_BG); +} + +/** + * @brief Generate break 2 event. + * @rmtoll EGR B2G LL_TIM_GenerateEvent_BRK2 + * @param TIMx Timer instance + * @retval None + */ +__STATIC_INLINE void LL_TIM_GenerateEvent_BRK2(TIM_TypeDef *TIMx) +{ + SET_BIT(TIMx->EGR, TIM_EGR_B2G); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup TIM_LL_EF_Init Initialisation and deinitialisation functions + * @{ + */ + +ErrorStatus LL_TIM_DeInit(const TIM_TypeDef *TIMx); +void LL_TIM_StructInit(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, 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, 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, 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, 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, const LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct); +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* TIM1 || TIM8 || TIM2 || TIM3 || TIM4 || TIM5 || TIM15 || TIM16 || TIM17 || TIM6 || TIM7 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_LL_TIM_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usart.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usart.h new file mode 100644 index 0000000..322bd2f --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_usart.h @@ -0,0 +1,4699 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_usart.h + * @author MCD Application Team + * @brief Header file of USART 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 STM32L4xx_LL_USART_H +#define STM32L4xx_LL_USART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(USART1) || defined(USART2) || defined(USART3) || defined(UART4) || defined(UART5) + +/** @defgroup USART_LL USART + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +#if defined(USART_PRESC_PRESCALER) +/** @defgroup USART_LL_Private_Variables USART Private Variables + * @{ + */ +/* Array used to get the USART prescaler division decimal values versus @ref USART_LL_EC_PRESCALER values */ +static const uint32_t USART_PRESCALER_TAB[] = +{ + 1UL, + 2UL, + 4UL, + 6UL, + 8UL, + 10UL, + 12UL, + 16UL, + 32UL, + 64UL, + 128UL, + 256UL +}; +/** + * @} + */ +#endif /* USART_PRESC_PRESCALER */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup USART_LL_Private_Constants USART Private Constants + * @{ + */ +/** + * @} + */ +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_Private_Macros USART Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_ES_INIT USART Exported Init structures + * @{ + */ + +/** + * @brief LL USART Init Structure definition + */ +typedef struct +{ +#if defined(USART_PRESC_PRESCALER) + uint32_t PrescalerValue; /*!< Specifies the Prescaler to compute the communication baud rate. + This parameter can be a value of @ref USART_LL_EC_PRESCALER. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetPrescaler().*/ +#endif /* USART_PRESC_PRESCALER */ + + uint32_t BaudRate; /*!< This field defines expected Usart communication baud rate. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetBaudRate().*/ + + uint32_t DataWidth; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref USART_LL_EC_DATAWIDTH. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetDataWidth().*/ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref USART_LL_EC_STOPBITS. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetStopBitsLength().*/ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref USART_LL_EC_PARITY. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetParity().*/ + + uint32_t TransferDirection; /*!< Specifies whether the Receive and/or Transmit mode is enabled or disabled. + This parameter can be a value of @ref USART_LL_EC_DIRECTION. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetTransferDirection().*/ + + uint32_t HardwareFlowControl; /*!< Specifies whether the hardware flow control mode is enabled or disabled. + This parameter can be a value of @ref USART_LL_EC_HWCONTROL. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetHWFlowCtrl().*/ + + uint32_t OverSampling; /*!< Specifies whether USART oversampling mode is 16 or 8. + This parameter can be a value of @ref USART_LL_EC_OVERSAMPLING. + + This feature can be modified afterwards using unitary + function @ref LL_USART_SetOverSampling().*/ + +} LL_USART_InitTypeDef; + +/** + * @brief LL USART Clock Init Structure definition + */ +typedef struct +{ + uint32_t ClockOutput; /*!< Specifies whether the USART clock is enabled or disabled. + This parameter can be a value of @ref USART_LL_EC_CLOCK. + + USART HW configuration can be modified afterwards using unitary functions + @ref LL_USART_EnableSCLKOutput() or @ref LL_USART_DisableSCLKOutput(). + For more details, refer to description of this function. */ + + uint32_t ClockPolarity; /*!< Specifies the steady state of the serial clock. + This parameter can be a value of @ref USART_LL_EC_POLARITY. + + USART HW configuration can be modified afterwards using unitary + functions @ref LL_USART_SetClockPolarity(). + For more details, refer to description of this function. */ + + uint32_t ClockPhase; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref USART_LL_EC_PHASE. + + USART HW configuration can be modified afterwards using unitary + functions @ref LL_USART_SetClockPhase(). + For more details, refer to description of this function. */ + + uint32_t LastBitClockPulse; /*!< Specifies whether the clock pulse corresponding to the last transmitted + data bit (MSB) has to be output on the SCLK pin in synchronous mode. + This parameter can be a value of @ref USART_LL_EC_LASTCLKPULSE. + + USART HW configuration can be modified afterwards using unitary + functions @ref LL_USART_SetLastClkPulseOutput(). + For more details, refer to description of this function. */ + +} LL_USART_ClockInitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup USART_LL_Exported_Constants USART Exported Constants + * @{ + */ + +/** @defgroup USART_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_USART_WriteReg function + * @{ + */ +#define LL_USART_ICR_PECF USART_ICR_PECF /*!< Parity error clear flag */ +#define LL_USART_ICR_FECF USART_ICR_FECF /*!< Framing error clear flag */ +#define LL_USART_ICR_NECF USART_ICR_NECF /*!< Noise error detected clear flag */ +#define LL_USART_ICR_ORECF USART_ICR_ORECF /*!< Overrun error clear flag */ +#define LL_USART_ICR_IDLECF USART_ICR_IDLECF /*!< Idle line detected clear flag */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_ICR_TXFECF USART_ICR_TXFECF /*!< TX FIFO Empty clear flag */ +#endif /* USART_CR1_FIFOEN */ +#define LL_USART_ICR_TCCF USART_ICR_TCCF /*!< Transmission complete clear flag */ +#if defined(USART_TCBGT_SUPPORT) +#define LL_USART_ICR_TCBGTCF USART_ICR_TCBGTCF /*!< Transmission completed before guard time clear flag */ +#endif /* USART_TCBGT_SUPPORT */ +#define LL_USART_ICR_LBDCF USART_ICR_LBDCF /*!< LIN break detection clear flag */ +#define LL_USART_ICR_CTSCF USART_ICR_CTSCF /*!< CTS clear flag */ +#define LL_USART_ICR_RTOCF USART_ICR_RTOCF /*!< Receiver timeout clear flag */ +#define LL_USART_ICR_EOBCF USART_ICR_EOBCF /*!< End of block clear flag */ +#if defined(USART_CR2_SLVEN) +#define LL_USART_ICR_UDRCF USART_ICR_UDRCF /*!< SPI Slave Underrun clear flag */ +#endif /* USART_CR2_SLVEN */ +#define LL_USART_ICR_CMCF USART_ICR_CMCF /*!< Character match clear flag */ +#define LL_USART_ICR_WUCF USART_ICR_WUCF /*!< Wakeup from Stop mode clear flag */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_USART_ReadReg function + * @{ + */ +#define LL_USART_ISR_PE USART_ISR_PE /*!< Parity error flag */ +#define LL_USART_ISR_FE USART_ISR_FE /*!< Framing error flag */ +#define LL_USART_ISR_NE USART_ISR_NE /*!< Noise detected flag */ +#define LL_USART_ISR_ORE USART_ISR_ORE /*!< Overrun error flag */ +#define LL_USART_ISR_IDLE USART_ISR_IDLE /*!< Idle line detected flag */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_ISR_RXNE_RXFNE USART_ISR_RXNE_RXFNE /*!< Read data register or RX FIFO not empty flag */ +#else +#define LL_USART_ISR_RXNE USART_ISR_RXNE /*!< Read data register not empty flag */ +#endif /* USART_CR1_FIFOEN */ +#define LL_USART_ISR_TC USART_ISR_TC /*!< Transmission complete flag */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_ISR_TXE_TXFNF USART_ISR_TXE_TXFNF /*!< Transmit data register empty or TX FIFO Not Full flag*/ +#else +#define LL_USART_ISR_TXE USART_ISR_TXE /*!< Transmit data register empty flag */ +#endif /* USART_CR1_FIFOEN */ +#define LL_USART_ISR_LBDF USART_ISR_LBDF /*!< LIN break detection flag */ +#define LL_USART_ISR_CTSIF USART_ISR_CTSIF /*!< CTS interrupt flag */ +#define LL_USART_ISR_CTS USART_ISR_CTS /*!< CTS flag */ +#define LL_USART_ISR_RTOF USART_ISR_RTOF /*!< Receiver timeout flag */ +#define LL_USART_ISR_EOBF USART_ISR_EOBF /*!< End of block flag */ +#if defined(USART_CR2_SLVEN) +#define LL_USART_ISR_UDR USART_ISR_UDR /*!< SPI Slave underrun error flag */ +#endif /* USART_CR2_SLVEN */ +#define LL_USART_ISR_ABRE USART_ISR_ABRE /*!< Auto baud rate error flag */ +#define LL_USART_ISR_ABRF USART_ISR_ABRF /*!< Auto baud rate flag */ +#define LL_USART_ISR_BUSY USART_ISR_BUSY /*!< Busy flag */ +#define LL_USART_ISR_CMF USART_ISR_CMF /*!< Character match flag */ +#define LL_USART_ISR_SBKF USART_ISR_SBKF /*!< Send break flag */ +#define LL_USART_ISR_RWU USART_ISR_RWU /*!< Receiver wakeup from Mute mode flag */ +#define LL_USART_ISR_WUF USART_ISR_WUF /*!< Wakeup from Stop mode flag */ +#define LL_USART_ISR_TEACK USART_ISR_TEACK /*!< Transmit enable acknowledge flag */ +#define LL_USART_ISR_REACK USART_ISR_REACK /*!< Receive enable acknowledge flag */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_ISR_TXFE USART_ISR_TXFE /*!< TX FIFO empty flag */ +#define LL_USART_ISR_RXFF USART_ISR_RXFF /*!< RX FIFO full flag */ +#endif /* USART_CR1_FIFOEN */ +#if defined(USART_TCBGT_SUPPORT) +#define LL_USART_ISR_TCBGT USART_ISR_TCBGT /*!< Transmission complete before guard time completion flag */ +#endif /* USART_TCBGT_SUPPORT */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_ISR_RXFT USART_ISR_RXFT /*!< RX FIFO threshold flag */ +#define LL_USART_ISR_TXFT USART_ISR_TXFT /*!< TX FIFO threshold flag */ +#endif /* USART_CR1_FIFOEN */ +/** + * @} + */ + +/** @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 */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_CR1_RXNEIE_RXFNEIE USART_CR1_RXNEIE_RXFNEIE /*!< Read data register and RXFIFO not empty interrupt enable */ +#else +#define LL_USART_CR1_RXNEIE USART_CR1_RXNEIE /*!< Read data register not empty interrupt enable */ +#endif /* USART_CR1_FIFOEN */ +#define LL_USART_CR1_TCIE USART_CR1_TCIE /*!< Transmission complete interrupt enable */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_CR1_TXEIE_TXFNFIE USART_CR1_TXEIE_TXFNFIE /*!< Transmit data register empty and TX FIFO not full interrupt enable */ +#else +#define LL_USART_CR1_TXEIE USART_CR1_TXEIE /*!< Transmit data register empty interrupt enable */ +#endif /* USART_CR1_FIFOEN */ +#define LL_USART_CR1_PEIE USART_CR1_PEIE /*!< Parity error */ +#define LL_USART_CR1_CMIE USART_CR1_CMIE /*!< Character match interrupt enable */ +#define LL_USART_CR1_RTOIE USART_CR1_RTOIE /*!< Receiver timeout interrupt enable */ +#define LL_USART_CR1_EOBIE USART_CR1_EOBIE /*!< End of Block interrupt enable */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_CR1_TXFEIE USART_CR1_TXFEIE /*!< TX FIFO empty interrupt enable */ +#define LL_USART_CR1_RXFFIE USART_CR1_RXFFIE /*!< RX FIFO full interrupt enable */ +#endif /* USART_CR1_FIFOEN */ +#define LL_USART_CR2_LBDIE USART_CR2_LBDIE /*!< LIN break detection interrupt enable */ +#define LL_USART_CR3_EIE USART_CR3_EIE /*!< Error interrupt enable */ +#define LL_USART_CR3_CTSIE USART_CR3_CTSIE /*!< CTS interrupt enable */ +#define LL_USART_CR3_WUFIE USART_CR3_WUFIE /*!< Wakeup from Stop mode interrupt enable */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_CR3_TXFTIE USART_CR3_TXFTIE /*!< TX FIFO threshold interrupt enable */ +#endif /* USART_CR1_FIFOEN */ +#if defined(USART_TCBGT_SUPPORT) +#define LL_USART_CR3_TCBGTIE USART_CR3_TCBGTIE /*!< Transmission complete before guard time interrupt enable */ +#endif /* USART_TCBGT_SUPPORT */ +#if defined(USART_CR1_FIFOEN) +#define LL_USART_CR3_RXFTIE USART_CR3_RXFTIE /*!< RX FIFO threshold interrupt enable */ +#endif /* USART_CR1_FIFOEN */ +/** + * @} + */ + +#if defined(USART_CR1_FIFOEN) +/** @defgroup USART_LL_EC_FIFOTHRESHOLD FIFO Threshold + * @{ + */ +#define LL_USART_FIFOTHRESHOLD_1_8 0x00000000U /*!< FIFO reaches 1/8 of its depth */ +#define LL_USART_FIFOTHRESHOLD_1_4 0x00000001U /*!< FIFO reaches 1/4 of its depth */ +#define LL_USART_FIFOTHRESHOLD_1_2 0x00000002U /*!< FIFO reaches 1/2 of its depth */ +#define LL_USART_FIFOTHRESHOLD_3_4 0x00000003U /*!< FIFO reaches 3/4 of its depth */ +#define LL_USART_FIFOTHRESHOLD_7_8 0x00000004U /*!< FIFO reaches 7/8 of its depth */ +#define LL_USART_FIFOTHRESHOLD_8_8 0x00000005U /*!< FIFO becomes empty for TX and full for RX */ +/** + * @} + */ + +#endif /* USART_CR1_FIFOEN */ +/** @defgroup USART_LL_EC_DIRECTION Communication Direction + * @{ + */ +#define LL_USART_DIRECTION_NONE 0x00000000U /*!< Transmitter and Receiver are disabled */ +#define LL_USART_DIRECTION_RX USART_CR1_RE /*!< Transmitter is disabled and Receiver is enabled */ +#define LL_USART_DIRECTION_TX USART_CR1_TE /*!< Transmitter is enabled and Receiver is disabled */ +#define LL_USART_DIRECTION_TX_RX (USART_CR1_TE |USART_CR1_RE) /*!< Transmitter and Receiver are enabled */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_PARITY Parity Control + * @{ + */ +#define LL_USART_PARITY_NONE 0x00000000U /*!< Parity control disabled */ +#define LL_USART_PARITY_EVEN USART_CR1_PCE /*!< Parity control enabled and Even Parity is selected */ +#define LL_USART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) /*!< Parity control enabled and Odd Parity is selected */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_WAKEUP Wakeup + * @{ + */ +#define LL_USART_WAKEUP_IDLELINE 0x00000000U /*!< USART wake up from Mute mode on Idle Line */ +#define LL_USART_WAKEUP_ADDRESSMARK USART_CR1_WAKE /*!< USART wake up from Mute mode on Address Mark */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DATAWIDTH Datawidth + * @{ + */ +#define LL_USART_DATAWIDTH_7B USART_CR1_M1 /*!< 7 bits word length : Start bit, 7 data bits, n stop bits */ +#define LL_USART_DATAWIDTH_8B 0x00000000U /*!< 8 bits word length : Start bit, 8 data bits, n stop bits */ +#define LL_USART_DATAWIDTH_9B USART_CR1_M0 /*!< 9 bits word length : Start bit, 9 data bits, n stop bits */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_OVERSAMPLING Oversampling + * @{ + */ +#define LL_USART_OVERSAMPLING_16 0x00000000U /*!< Oversampling by 16 */ +#define LL_USART_OVERSAMPLING_8 USART_CR1_OVER8 /*!< Oversampling by 8 */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_EC_CLOCK Clock Signal + * @{ + */ + +#define LL_USART_CLOCK_DISABLE 0x00000000U /*!< Clock signal not provided */ +#define LL_USART_CLOCK_ENABLE USART_CR2_CLKEN /*!< Clock signal provided */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/** @defgroup USART_LL_EC_LASTCLKPULSE Last Clock Pulse + * @{ + */ +#define LL_USART_LASTCLKPULSE_NO_OUTPUT 0x00000000U /*!< The clock pulse of the last data bit is not output to the SCLK pin */ +#define LL_USART_LASTCLKPULSE_OUTPUT USART_CR2_LBCL /*!< The clock pulse of the last data bit is output to the SCLK pin */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_USART_PHASE_1EDGE 0x00000000U /*!< The first clock transition is the first data capture edge */ +#define LL_USART_PHASE_2EDGE USART_CR2_CPHA /*!< The second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_USART_POLARITY_LOW 0x00000000U /*!< Steady low value on SCLK pin outside transmission window*/ +#define LL_USART_POLARITY_HIGH USART_CR2_CPOL /*!< Steady high value on SCLK pin outside transmission window */ +/** + * @} + */ + +#if defined(USART_PRESC_PRESCALER) +/** @defgroup USART_LL_EC_PRESCALER Clock Source Prescaler + * @{ + */ +#define LL_USART_PRESCALER_DIV1 0x00000000U /*!< Input clock not divided */ +#define LL_USART_PRESCALER_DIV2 (USART_PRESC_PRESCALER_0) /*!< Input clock divided by 2 */ +#define LL_USART_PRESCALER_DIV4 (USART_PRESC_PRESCALER_1) /*!< Input clock divided by 4 */ +#define LL_USART_PRESCALER_DIV6 (USART_PRESC_PRESCALER_1 | USART_PRESC_PRESCALER_0) /*!< Input clock divided by 6 */ +#define LL_USART_PRESCALER_DIV8 (USART_PRESC_PRESCALER_2) /*!< Input clock divided by 8 */ +#define LL_USART_PRESCALER_DIV10 (USART_PRESC_PRESCALER_2 | USART_PRESC_PRESCALER_0) /*!< Input clock divided by 10 */ +#define LL_USART_PRESCALER_DIV12 (USART_PRESC_PRESCALER_2 | USART_PRESC_PRESCALER_1) /*!< Input clock divided by 12 */ +#define LL_USART_PRESCALER_DIV16 (USART_PRESC_PRESCALER_2 | USART_PRESC_PRESCALER_1 | USART_PRESC_PRESCALER_0) /*!< Input clock divided by 16 */ +#define LL_USART_PRESCALER_DIV32 (USART_PRESC_PRESCALER_3) /*!< Input clock divided by 32 */ +#define LL_USART_PRESCALER_DIV64 (USART_PRESC_PRESCALER_3 | USART_PRESC_PRESCALER_0) /*!< Input clock divided by 64 */ +#define LL_USART_PRESCALER_DIV128 (USART_PRESC_PRESCALER_3 | USART_PRESC_PRESCALER_1) /*!< Input clock divided by 128 */ +#define LL_USART_PRESCALER_DIV256 (USART_PRESC_PRESCALER_3 | USART_PRESC_PRESCALER_1 | USART_PRESC_PRESCALER_0) /*!< Input clock divided by 256 */ +/** + * @} + */ + +#endif /* USART_PRESC_PRESCALER */ +/** @defgroup USART_LL_EC_STOPBITS Stop Bits + * @{ + */ +#define LL_USART_STOPBITS_0_5 USART_CR2_STOP_0 /*!< 0.5 stop bit */ +#define LL_USART_STOPBITS_1 0x00000000U /*!< 1 stop bit */ +#define LL_USART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) /*!< 1.5 stop bits */ +#define LL_USART_STOPBITS_2 USART_CR2_STOP_1 /*!< 2 stop bits */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_TXRX TX RX Pins Swap + * @{ + */ +#define LL_USART_TXRX_STANDARD 0x00000000U /*!< TX/RX pins are used as defined in standard pinout */ +#define LL_USART_TXRX_SWAPPED (USART_CR2_SWAP) /*!< TX and RX pins functions are swapped. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_RXPIN_LEVEL RX Pin Active Level Inversion + * @{ + */ +#define LL_USART_RXPIN_LEVEL_STANDARD 0x00000000U /*!< RX pin signal works using the standard logic levels */ +#define LL_USART_RXPIN_LEVEL_INVERTED (USART_CR2_RXINV) /*!< RX pin signal values are inverted. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_TXPIN_LEVEL TX Pin Active Level Inversion + * @{ + */ +#define LL_USART_TXPIN_LEVEL_STANDARD 0x00000000U /*!< TX pin signal works using the standard logic levels */ +#define LL_USART_TXPIN_LEVEL_INVERTED (USART_CR2_TXINV) /*!< TX pin signal values are inverted. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_BINARY_LOGIC Binary Data Inversion + * @{ + */ +#define LL_USART_BINARY_LOGIC_POSITIVE 0x00000000U /*!< Logical data from the data register are send/received in positive/direct logic. (1=H, 0=L) */ +#define LL_USART_BINARY_LOGIC_NEGATIVE USART_CR2_DATAINV /*!< Logical data from the data register are send/received in negative/inverse logic. (1=L, 0=H). The parity bit is also inverted. */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_BITORDER Bit Order + * @{ + */ +#define LL_USART_BITORDER_LSBFIRST 0x00000000U /*!< data is transmitted/received with data bit 0 first, following the start bit */ +#define LL_USART_BITORDER_MSBFIRST USART_CR2_MSBFIRST /*!< data is transmitted/received with the MSB first, following the start bit */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_AUTOBAUD_DETECT_ON Autobaud Detection + * @{ + */ +#define LL_USART_AUTOBAUD_DETECT_ON_STARTBIT 0x00000000U /*!< Measurement of the start bit is used to detect the baud rate */ +#define LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE USART_CR2_ABRMODE_0 /*!< Falling edge to falling edge measurement. Received frame must start with a single bit = 1 -> Frame = Start10xxxxxx */ +#define LL_USART_AUTOBAUD_DETECT_ON_7F_FRAME USART_CR2_ABRMODE_1 /*!< 0x7F frame detection */ +#define LL_USART_AUTOBAUD_DETECT_ON_55_FRAME (USART_CR2_ABRMODE_1 | USART_CR2_ABRMODE_0) /*!< 0x55 frame detection */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_ADDRESS_DETECT Address Length Detection + * @{ + */ +#define LL_USART_ADDRESS_DETECT_4B 0x00000000U /*!< 4-bit address detection method selected */ +#define LL_USART_ADDRESS_DETECT_7B USART_CR2_ADDM7 /*!< 7-bit address detection (in 8-bit data mode) method selected */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_HWCONTROL Hardware Control + * @{ + */ +#define LL_USART_HWCONTROL_NONE 0x00000000U /*!< CTS and RTS hardware flow control disabled */ +#define LL_USART_HWCONTROL_RTS USART_CR3_RTSE /*!< RTS output enabled, data is only requested when there is space in the receive buffer */ +#define LL_USART_HWCONTROL_CTS USART_CR3_CTSE /*!< CTS mode enabled, data is only transmitted when the nCTS input is asserted (tied to 0) */ +#define LL_USART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) /*!< CTS and RTS hardware flow control enabled */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_WAKEUP_ON Wakeup Activation + * @{ + */ +#define LL_USART_WAKEUP_ON_ADDRESS 0x00000000U /*!< Wake up active on address match */ +#define LL_USART_WAKEUP_ON_STARTBIT USART_CR3_WUS_1 /*!< Wake up active on Start bit detection */ +#define LL_USART_WAKEUP_ON_RXNE (USART_CR3_WUS_0 | USART_CR3_WUS_1) /*!< Wake up active on RXNE */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_IRDA_POWER IrDA Power + * @{ + */ +#define LL_USART_IRDA_POWER_NORMAL 0x00000000U /*!< IrDA normal power mode */ +#define LL_USART_IRDA_POWER_LOW USART_CR3_IRLP /*!< IrDA low power mode */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_LINBREAK_DETECT LIN Break Detection Length + * @{ + */ +#define LL_USART_LINBREAK_DETECT_10B 0x00000000U /*!< 10-bit break detection method selected */ +#define LL_USART_LINBREAK_DETECT_11B USART_CR2_LBDL /*!< 11-bit break detection method selected */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DE_POLARITY Driver Enable Polarity + * @{ + */ +#define LL_USART_DE_POLARITY_HIGH 0x00000000U /*!< DE signal is active high */ +#define LL_USART_DE_POLARITY_LOW USART_CR3_DEP /*!< DE signal is active low */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_DMA_REG_DATA DMA Register Data + * @{ + */ +#define LL_USART_DMA_REG_DATA_TRANSMIT 0x00000000U /*!< Get address of data register used for transmission */ +#define LL_USART_DMA_REG_DATA_RECEIVE 0x00000001U /*!< Get address of data register used for reception */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup USART_LL_Exported_Macros USART Exported Macros + * @{ + */ + +/** @defgroup USART_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in USART register + * @param __INSTANCE__ USART Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_USART_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in USART register + * @param __INSTANCE__ USART Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_USART_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup USART_LL_EM_Exported_Macros_Helper Exported_Macros_Helper + * @{ + */ + +/** + * @brief Compute USARTDIV value according to Peripheral Clock and + * expected Baud Rate in 8 bits sampling mode (32 bits value of USARTDIV is returned) + * @param __PERIPHCLK__ Peripheral Clock frequency used for USART instance + @if USART_PRESC_PRESCALER + * @param __PRESCALER__ This parameter can be one of the following values: + * @arg @ref LL_USART_PRESCALER_DIV1 + * @arg @ref LL_USART_PRESCALER_DIV2 + * @arg @ref LL_USART_PRESCALER_DIV4 + * @arg @ref LL_USART_PRESCALER_DIV6 + * @arg @ref LL_USART_PRESCALER_DIV8 + * @arg @ref LL_USART_PRESCALER_DIV10 + * @arg @ref LL_USART_PRESCALER_DIV12 + * @arg @ref LL_USART_PRESCALER_DIV16 + * @arg @ref LL_USART_PRESCALER_DIV32 + * @arg @ref LL_USART_PRESCALER_DIV64 + * @arg @ref LL_USART_PRESCALER_DIV128 + * @arg @ref LL_USART_PRESCALER_DIV256 + @endif + * @param __BAUDRATE__ Baud rate value to achieve + * @retval USARTDIV value to be used for BRR register filling in OverSampling_8 case + */ +#if defined(USART_PRESC_PRESCALER) +#define __LL_USART_DIV_SAMPLING8(__PERIPHCLK__, __PRESCALER__, __BAUDRATE__) \ + (((((__PERIPHCLK__)/(USART_PRESCALER_TAB[(__PRESCALER__)]))*2U)\ + + ((__BAUDRATE__)/2U))/(__BAUDRATE__)) +#else +#define __LL_USART_DIV_SAMPLING8(__PERIPHCLK__, __BAUDRATE__) ((((__PERIPHCLK__)*2U)\ + + ((__BAUDRATE__)/2U))/(__BAUDRATE__)) +#endif /* USART_PRESC_PRESCALER */ + +/** + * @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 + @if USART_PRESC_PRESCALER + * @param __PRESCALER__ This parameter can be one of the following values: + * @arg @ref LL_USART_PRESCALER_DIV1 + * @arg @ref LL_USART_PRESCALER_DIV2 + * @arg @ref LL_USART_PRESCALER_DIV4 + * @arg @ref LL_USART_PRESCALER_DIV6 + * @arg @ref LL_USART_PRESCALER_DIV8 + * @arg @ref LL_USART_PRESCALER_DIV10 + * @arg @ref LL_USART_PRESCALER_DIV12 + * @arg @ref LL_USART_PRESCALER_DIV16 + * @arg @ref LL_USART_PRESCALER_DIV32 + * @arg @ref LL_USART_PRESCALER_DIV64 + * @arg @ref LL_USART_PRESCALER_DIV128 + * @arg @ref LL_USART_PRESCALER_DIV256 + @endif + * @param __BAUDRATE__ Baud rate value to achieve + * @retval USARTDIV value to be used for BRR register filling in OverSampling_16 case + */ +#if defined(USART_PRESC_PRESCALER) +#define __LL_USART_DIV_SAMPLING16(__PERIPHCLK__, __PRESCALER__, __BAUDRATE__) \ + ((((__PERIPHCLK__)/(USART_PRESCALER_TAB[(__PRESCALER__)]))\ + + ((__BAUDRATE__)/2U))/(__BAUDRATE__)) +#else +#define __LL_USART_DIV_SAMPLING16(__PERIPHCLK__, __BAUDRATE__) (((__PERIPHCLK__) + ((__BAUDRATE__)/2U))/(__BAUDRATE__)) +#endif /* USART_PRESC_PRESCALER */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup USART_LL_Exported_Functions USART Exported Functions + * @{ + */ + +/** @defgroup USART_LL_EF_Configuration Configuration functions + * @{ + */ + +/** + * @brief USART Enable + * @rmtoll CR1 UE LL_USART_Enable + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_Enable(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR1, USART_CR1_UE); +} + +/** + * @brief USART Disable (all USART prescalers and outputs are disabled) + * @note When USART is disabled, USART prescalers and outputs are stopped immediately, + * and current operations are discarded. The configuration of the USART is kept, but all the status + * flags, in the USARTx_ISR are set to their default values. + * @rmtoll CR1 UE LL_USART_Disable + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_Disable(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR1, USART_CR1_UE); +} + +/** + * @brief Indicate if USART is enabled + * @rmtoll CR1 UE LL_USART_IsEnabled + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabled(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_UE) == (USART_CR1_UE)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief FIFO Mode Enable + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 FIFOEN LL_USART_EnableFIFO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableFIFO(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR1, USART_CR1_FIFOEN); +} + +/** + * @brief FIFO Mode Disable + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 FIFOEN LL_USART_DisableFIFO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableFIFO(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR1, USART_CR1_FIFOEN); +} + +/** + * @brief Indicate if FIFO Mode is enabled + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 FIFOEN LL_USART_IsEnabledFIFO + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledFIFO(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_FIFOEN) == (USART_CR1_FIFOEN)) ? 1UL : 0UL); +} + +/** + * @brief Configure TX FIFO Threshold + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 TXFTCFG LL_USART_SetTXFIFOThreshold + * @param USARTx USART Instance + * @param Threshold This parameter can be one of the following values: + * @arg @ref LL_USART_FIFOTHRESHOLD_1_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_2 + * @arg @ref LL_USART_FIFOTHRESHOLD_3_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_7_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_8_8 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTXFIFOThreshold(USART_TypeDef *USARTx, uint32_t Threshold) +{ + ATOMIC_MODIFY_REG(USARTx->CR3, USART_CR3_TXFTCFG, Threshold << USART_CR3_TXFTCFG_Pos); +} + +/** + * @brief Return TX FIFO Threshold Configuration + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 TXFTCFG LL_USART_GetTXFIFOThreshold + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_FIFOTHRESHOLD_1_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_2 + * @arg @ref LL_USART_FIFOTHRESHOLD_3_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_7_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_8_8 + */ +__STATIC_INLINE uint32_t LL_USART_GetTXFIFOThreshold(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos); +} + +/** + * @brief Configure RX FIFO Threshold + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 RXFTCFG LL_USART_SetRXFIFOThreshold + * @param USARTx USART Instance + * @param Threshold This parameter can be one of the following values: + * @arg @ref LL_USART_FIFOTHRESHOLD_1_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_2 + * @arg @ref LL_USART_FIFOTHRESHOLD_3_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_7_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_8_8 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetRXFIFOThreshold(USART_TypeDef *USARTx, uint32_t Threshold) +{ + ATOMIC_MODIFY_REG(USARTx->CR3, USART_CR3_RXFTCFG, Threshold << USART_CR3_RXFTCFG_Pos); +} + +/** + * @brief Return RX FIFO Threshold Configuration + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 RXFTCFG LL_USART_GetRXFIFOThreshold + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_FIFOTHRESHOLD_1_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_2 + * @arg @ref LL_USART_FIFOTHRESHOLD_3_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_7_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_8_8 + */ +__STATIC_INLINE uint32_t LL_USART_GetRXFIFOThreshold(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos); +} + +/** + * @brief Configure TX and RX FIFOs Threshold + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 TXFTCFG LL_USART_ConfigFIFOsThreshold\n + * CR3 RXFTCFG LL_USART_ConfigFIFOsThreshold + * @param USARTx USART Instance + * @param TXThreshold This parameter can be one of the following values: + * @arg @ref LL_USART_FIFOTHRESHOLD_1_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_2 + * @arg @ref LL_USART_FIFOTHRESHOLD_3_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_7_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_8_8 + * @param RXThreshold This parameter can be one of the following values: + * @arg @ref LL_USART_FIFOTHRESHOLD_1_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_1_2 + * @arg @ref LL_USART_FIFOTHRESHOLD_3_4 + * @arg @ref LL_USART_FIFOTHRESHOLD_7_8 + * @arg @ref LL_USART_FIFOTHRESHOLD_8_8 + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigFIFOsThreshold(USART_TypeDef *USARTx, uint32_t TXThreshold, uint32_t RXThreshold) +{ + ATOMIC_MODIFY_REG(USARTx->CR3, USART_CR3_TXFTCFG | USART_CR3_RXFTCFG, (TXThreshold << USART_CR3_TXFTCFG_Pos) | + (RXThreshold << USART_CR3_RXFTCFG_Pos)); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief USART enabled in STOP Mode. + * @note When this function is enabled, USART is able to wake up the MCU from Stop mode, provided that + * USART clock selection is HSI or LSE in RCC. + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR1 UESM LL_USART_EnableInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_UESM); +} + +/** + * @brief USART disabled in STOP Mode. + * @note When this function is disabled, USART is not able to wake up the MCU from Stop mode + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR1 UESM LL_USART_DisableInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_UESM); +} + +/** + * @brief Indicate if USART is enabled in STOP Mode (able to wake up MCU from Stop mode or not) + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR1 UESM LL_USART_IsEnabledInStopMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledInStopMode(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_UESM) == (USART_CR1_UESM)) ? 1UL : 0UL); +} + +#if defined(USART_CR3_UCESM) +/** + * @brief USART Clock enabled in STOP Mode + * @note When this function is called, USART Clock is enabled while in STOP mode + * @rmtoll CR3 UCESM LL_USART_EnableClockInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableClockInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_UCESM); +} + +/** + * @brief USART clock disabled in STOP Mode + * @note When this function is called, USART Clock is disabled while in STOP mode + * @rmtoll CR3 UCESM LL_USART_DisableClockInStopMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableClockInStopMode(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_UCESM); +} + +/** + * @brief Indicate if USART clock is enabled in STOP Mode + * @rmtoll CR3 UCESM LL_USART_IsClockEnabledInStopMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsClockEnabledInStopMode(const USART_TypeDef *USARTx) +{ + return (READ_BIT(USARTx->CR3, USART_CR3_UCESM) == (USART_CR3_UCESM)); +} + +#endif /* USART_CR3_UCESM */ +/** + * @brief Receiver Enable (Receiver is enabled and begins searching for a start bit) + * @rmtoll CR1 RE LL_USART_EnableDirectionRx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDirectionRx(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RE); +} + +/** + * @brief Receiver Disable + * @rmtoll CR1 RE LL_USART_DisableDirectionRx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDirectionRx(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RE); +} + +/** + * @brief Transmitter Enable + * @rmtoll CR1 TE LL_USART_EnableDirectionTx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDirectionTx(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_TE); +} + +/** + * @brief Transmitter Disable + * @rmtoll CR1 TE LL_USART_DisableDirectionTx + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDirectionTx(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_TE); +} + +/** + * @brief Configure simultaneously enabled/disabled states + * of Transmitter and Receiver + * @rmtoll CR1 RE LL_USART_SetTransferDirection\n + * CR1 TE LL_USART_SetTransferDirection + * @param USARTx USART Instance + * @param TransferDirection This parameter can be one of the following values: + * @arg @ref LL_USART_DIRECTION_NONE + * @arg @ref LL_USART_DIRECTION_RX + * @arg @ref LL_USART_DIRECTION_TX + * @arg @ref LL_USART_DIRECTION_TX_RX + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTransferDirection(USART_TypeDef *USARTx, uint32_t TransferDirection) +{ + ATOMIC_MODIFY_REG(USARTx->CR1, USART_CR1_RE | USART_CR1_TE, TransferDirection); +} + +/** + * @brief Return enabled/disabled states of Transmitter and Receiver + * @rmtoll CR1 RE LL_USART_GetTransferDirection\n + * CR1 TE LL_USART_GetTransferDirection + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DIRECTION_NONE + * @arg @ref LL_USART_DIRECTION_RX + * @arg @ref LL_USART_DIRECTION_TX + * @arg @ref LL_USART_DIRECTION_TX_RX + */ +__STATIC_INLINE uint32_t LL_USART_GetTransferDirection(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 M0 LL_USART_SetDataWidth\n + * CR1 M1 LL_USART_SetDataWidth + * @param USARTx USART Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_7B + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDataWidth(USART_TypeDef *USARTx, uint32_t DataWidth) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_M, DataWidth); +} + +/** + * @brief Return Word length (i.e. nb of data bits, excluding start and stop bits) + * @rmtoll CR1 M0 LL_USART_GetDataWidth\n + * CR1 M1 LL_USART_GetDataWidth + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_7B + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + */ +__STATIC_INLINE uint32_t LL_USART_GetDataWidth(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_M)); +} + +/** + * @brief Allow switch between Mute Mode and Active mode + * @rmtoll CR1 MME LL_USART_EnableMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableMuteMode(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_MME); +} + +/** + * @brief Prevent Mute Mode use. Set Receiver in active mode permanently. + * @rmtoll CR1 MME LL_USART_DisableMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableMuteMode(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_MME); +} + +/** + * @brief Indicate if switch between Mute Mode and Active mode is allowed + * @rmtoll CR1 MME LL_USART_IsEnabledMuteMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledMuteMode(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_MME) == (USART_CR1_MME)) ? 1UL : 0UL); +} + +/** + * @brief Set Oversampling to 8-bit or 16-bit mode + * @rmtoll CR1 OVER8 LL_USART_SetOverSampling + * @param USARTx USART Instance + * @param OverSampling This parameter can be one of the following values: + * @arg @ref LL_USART_OVERSAMPLING_16 + * @arg @ref LL_USART_OVERSAMPLING_8 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetOverSampling(USART_TypeDef *USARTx, uint32_t OverSampling) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_OVER8, OverSampling); +} + +/** + * @brief Return Oversampling mode + * @rmtoll CR1 OVER8 LL_USART_GetOverSampling + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_OVERSAMPLING_16 + * @arg @ref LL_USART_OVERSAMPLING_8 + */ +__STATIC_INLINE uint32_t LL_USART_GetOverSampling(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 IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 LBCL LL_USART_SetLastClkPulseOutput + * @param USARTx USART Instance + * @param LastBitClockPulse This parameter can be one of the following values: + * @arg @ref LL_USART_LASTCLKPULSE_NO_OUTPUT + * @arg @ref LL_USART_LASTCLKPULSE_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_USART_SetLastClkPulseOutput(USART_TypeDef *USARTx, uint32_t LastBitClockPulse) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_LBCL, LastBitClockPulse); +} + +/** + * @brief Retrieve Clock pulse of the last data bit output configuration + * (Last bit Clock pulse output to the SCLK pin or not) + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 LBCL LL_USART_GetLastClkPulseOutput + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_LASTCLKPULSE_NO_OUTPUT + * @arg @ref LL_USART_LASTCLKPULSE_OUTPUT + */ +__STATIC_INLINE uint32_t LL_USART_GetLastClkPulseOutput(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_LBCL)); +} + +/** + * @brief Select the phase of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPHA LL_USART_SetClockPhase + * @param USARTx USART Instance + * @param ClockPhase This parameter can be one of the following values: + * @arg @ref LL_USART_PHASE_1EDGE + * @arg @ref LL_USART_PHASE_2EDGE + * @retval None + */ +__STATIC_INLINE void LL_USART_SetClockPhase(USART_TypeDef *USARTx, uint32_t ClockPhase) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_CPHA, ClockPhase); +} + +/** + * @brief Return phase of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPHA LL_USART_GetClockPhase + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_PHASE_1EDGE + * @arg @ref LL_USART_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_USART_GetClockPhase(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_CPHA)); +} + +/** + * @brief Select the polarity of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPOL LL_USART_SetClockPolarity + * @param USARTx USART Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_USART_POLARITY_LOW + * @arg @ref LL_USART_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_USART_SetClockPolarity(USART_TypeDef *USARTx, uint32_t ClockPolarity) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_CPOL, ClockPolarity); +} + +/** + * @brief Return polarity of the clock output on the SCLK pin in synchronous mode + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CPOL LL_USART_GetClockPolarity + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_POLARITY_LOW + * @arg @ref LL_USART_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_USART_GetClockPolarity(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_CPOL)); +} + +/** + * @brief Configure Clock signal format (Phase Polarity and choice about output of last bit clock pulse) + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clock Phase configuration using @ref LL_USART_SetClockPhase() function + * - Clock Polarity configuration using @ref LL_USART_SetClockPolarity() function + * - Output of Last bit Clock pulse configuration using @ref LL_USART_SetLastClkPulseOutput() function + * @rmtoll CR2 CPHA LL_USART_ConfigClock\n + * CR2 CPOL LL_USART_ConfigClock\n + * CR2 LBCL LL_USART_ConfigClock + * @param USARTx USART Instance + * @param Phase This parameter can be one of the following values: + * @arg @ref LL_USART_PHASE_1EDGE + * @arg @ref LL_USART_PHASE_2EDGE + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_USART_POLARITY_LOW + * @arg @ref LL_USART_POLARITY_HIGH + * @param LBCPOutput This parameter can be one of the following values: + * @arg @ref LL_USART_LASTCLKPULSE_NO_OUTPUT + * @arg @ref LL_USART_LASTCLKPULSE_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigClock(USART_TypeDef *USARTx, uint32_t Phase, uint32_t Polarity, uint32_t LBCPOutput) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL, Phase | Polarity | LBCPOutput); +} + +#if defined(USART_PRESC_PRESCALER) +/** + * @brief Configure Clock source prescaler for baudrate generator and oversampling + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll PRESC PRESCALER LL_USART_SetPrescaler + * @param USARTx USART Instance + * @param PrescalerValue This parameter can be one of the following values: + * @arg @ref LL_USART_PRESCALER_DIV1 + * @arg @ref LL_USART_PRESCALER_DIV2 + * @arg @ref LL_USART_PRESCALER_DIV4 + * @arg @ref LL_USART_PRESCALER_DIV6 + * @arg @ref LL_USART_PRESCALER_DIV8 + * @arg @ref LL_USART_PRESCALER_DIV10 + * @arg @ref LL_USART_PRESCALER_DIV12 + * @arg @ref LL_USART_PRESCALER_DIV16 + * @arg @ref LL_USART_PRESCALER_DIV32 + * @arg @ref LL_USART_PRESCALER_DIV64 + * @arg @ref LL_USART_PRESCALER_DIV128 + * @arg @ref LL_USART_PRESCALER_DIV256 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetPrescaler(USART_TypeDef *USARTx, uint32_t PrescalerValue) +{ + MODIFY_REG(USARTx->PRESC, USART_PRESC_PRESCALER, (uint16_t)PrescalerValue); +} + +/** + * @brief Retrieve the Clock source prescaler for baudrate generator and oversampling + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll PRESC PRESCALER LL_USART_GetPrescaler + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_PRESCALER_DIV1 + * @arg @ref LL_USART_PRESCALER_DIV2 + * @arg @ref LL_USART_PRESCALER_DIV4 + * @arg @ref LL_USART_PRESCALER_DIV6 + * @arg @ref LL_USART_PRESCALER_DIV8 + * @arg @ref LL_USART_PRESCALER_DIV10 + * @arg @ref LL_USART_PRESCALER_DIV12 + * @arg @ref LL_USART_PRESCALER_DIV16 + * @arg @ref LL_USART_PRESCALER_DIV32 + * @arg @ref LL_USART_PRESCALER_DIV64 + * @arg @ref LL_USART_PRESCALER_DIV128 + * @arg @ref LL_USART_PRESCALER_DIV256 + */ +__STATIC_INLINE uint32_t LL_USART_GetPrescaler(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->PRESC, USART_PRESC_PRESCALER)); +} + +#endif /* USART_PRESC_PRESCALER */ +/** + * @brief Enable Clock output on SCLK pin + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CLKEN LL_USART_EnableSCLKOutput + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSCLKOutput(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_CLKEN); +} + +/** + * @brief Disable Clock output on SCLK pin + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CLKEN LL_USART_DisableSCLKOutput + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSCLKOutput(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_CLKEN); +} + +/** + * @brief Indicate if Clock output on SCLK pin is enabled + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @rmtoll CR2 CLKEN LL_USART_IsEnabledSCLKOutput + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSCLKOutput(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_CLKEN) == (USART_CR2_CLKEN)) ? 1UL : 0UL); +} + +/** + * @brief Set the length of the stop bits + * @rmtoll CR2 STOP LL_USART_SetStopBitsLength + * @param USARTx USART Instance + * @param StopBits This parameter can be one of the following values: + * @arg @ref LL_USART_STOPBITS_0_5 + * @arg @ref LL_USART_STOPBITS_1 + * @arg @ref LL_USART_STOPBITS_1_5 + * @arg @ref LL_USART_STOPBITS_2 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetStopBitsLength(USART_TypeDef *USARTx, uint32_t StopBits) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_STOP, StopBits); +} + +/** + * @brief Retrieve the length of the stop bits + * @rmtoll CR2 STOP LL_USART_GetStopBitsLength + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_STOPBITS_0_5 + * @arg @ref LL_USART_STOPBITS_1 + * @arg @ref LL_USART_STOPBITS_1_5 + * @arg @ref LL_USART_STOPBITS_2 + */ +__STATIC_INLINE uint32_t LL_USART_GetStopBitsLength(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 M0 LL_USART_ConfigCharacter\n + * CR1 M1 LL_USART_ConfigCharacter\n + * CR2 STOP LL_USART_ConfigCharacter + * @param USARTx USART Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_USART_DATAWIDTH_7B + * @arg @ref LL_USART_DATAWIDTH_8B + * @arg @ref LL_USART_DATAWIDTH_9B + * @param Parity This parameter can be one of the following values: + * @arg @ref LL_USART_PARITY_NONE + * @arg @ref LL_USART_PARITY_EVEN + * @arg @ref LL_USART_PARITY_ODD + * @param StopBits This parameter can be one of the following values: + * @arg @ref LL_USART_STOPBITS_0_5 + * @arg @ref LL_USART_STOPBITS_1 + * @arg @ref LL_USART_STOPBITS_1_5 + * @arg @ref LL_USART_STOPBITS_2 + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigCharacter(USART_TypeDef *USARTx, uint32_t DataWidth, uint32_t Parity, + uint32_t StopBits) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_PS | USART_CR1_PCE | USART_CR1_M, Parity | DataWidth); + MODIFY_REG(USARTx->CR2, USART_CR2_STOP, StopBits); +} + +/** + * @brief Configure TX/RX pins swapping setting. + * @rmtoll CR2 SWAP LL_USART_SetTXRXSwap + * @param USARTx USART Instance + * @param SwapConfig This parameter can be one of the following values: + * @arg @ref LL_USART_TXRX_STANDARD + * @arg @ref LL_USART_TXRX_SWAPPED + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTXRXSwap(USART_TypeDef *USARTx, uint32_t SwapConfig) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_SWAP, SwapConfig); +} + +/** + * @brief Retrieve TX/RX pins swapping configuration. + * @rmtoll CR2 SWAP LL_USART_GetTXRXSwap + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_TXRX_STANDARD + * @arg @ref LL_USART_TXRX_SWAPPED + */ +__STATIC_INLINE uint32_t LL_USART_GetTXRXSwap(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_SWAP)); +} + +/** + * @brief Configure RX pin active level logic + * @rmtoll CR2 RXINV LL_USART_SetRXPinLevel + * @param USARTx USART Instance + * @param PinInvMethod This parameter can be one of the following values: + * @arg @ref LL_USART_RXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_RXPIN_LEVEL_INVERTED + * @retval None + */ +__STATIC_INLINE void LL_USART_SetRXPinLevel(USART_TypeDef *USARTx, uint32_t PinInvMethod) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_RXINV, PinInvMethod); +} + +/** + * @brief Retrieve RX pin active level logic configuration + * @rmtoll CR2 RXINV LL_USART_GetRXPinLevel + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_RXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_RXPIN_LEVEL_INVERTED + */ +__STATIC_INLINE uint32_t LL_USART_GetRXPinLevel(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_RXINV)); +} + +/** + * @brief Configure TX pin active level logic + * @rmtoll CR2 TXINV LL_USART_SetTXPinLevel + * @param USARTx USART Instance + * @param PinInvMethod This parameter can be one of the following values: + * @arg @ref LL_USART_TXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_TXPIN_LEVEL_INVERTED + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTXPinLevel(USART_TypeDef *USARTx, uint32_t PinInvMethod) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_TXINV, PinInvMethod); +} + +/** + * @brief Retrieve TX pin active level logic configuration + * @rmtoll CR2 TXINV LL_USART_GetTXPinLevel + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_TXPIN_LEVEL_STANDARD + * @arg @ref LL_USART_TXPIN_LEVEL_INVERTED + */ +__STATIC_INLINE uint32_t LL_USART_GetTXPinLevel(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_TXINV)); +} + +/** + * @brief Configure Binary data logic. + * @note Allow to define how Logical data from the data register are send/received : + * either in positive/direct logic (1=H, 0=L) or in negative/inverse logic (1=L, 0=H) + * @rmtoll CR2 DATAINV LL_USART_SetBinaryDataLogic + * @param USARTx USART Instance + * @param DataLogic This parameter can be one of the following values: + * @arg @ref LL_USART_BINARY_LOGIC_POSITIVE + * @arg @ref LL_USART_BINARY_LOGIC_NEGATIVE + * @retval None + */ +__STATIC_INLINE void LL_USART_SetBinaryDataLogic(USART_TypeDef *USARTx, uint32_t DataLogic) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_DATAINV, DataLogic); +} + +/** + * @brief Retrieve Binary data configuration + * @rmtoll CR2 DATAINV LL_USART_GetBinaryDataLogic + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_BINARY_LOGIC_POSITIVE + * @arg @ref LL_USART_BINARY_LOGIC_NEGATIVE + */ +__STATIC_INLINE uint32_t LL_USART_GetBinaryDataLogic(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_DATAINV)); +} + +/** + * @brief Configure transfer bit order (either Less or Most Significant Bit First) + * @note MSB First means data is transmitted/received with the MSB first, following the start bit. + * LSB First means data is transmitted/received with data bit 0 first, following the start bit. + * @rmtoll CR2 MSBFIRST LL_USART_SetTransferBitOrder + * @param USARTx USART Instance + * @param BitOrder This parameter can be one of the following values: + * @arg @ref LL_USART_BITORDER_LSBFIRST + * @arg @ref LL_USART_BITORDER_MSBFIRST + * @retval None + */ +__STATIC_INLINE void LL_USART_SetTransferBitOrder(USART_TypeDef *USARTx, uint32_t BitOrder) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_MSBFIRST, BitOrder); +} + +/** + * @brief Return transfer bit order (either Less or Most Significant Bit First) + * @note MSB First means data is transmitted/received with the MSB first, following the start bit. + * LSB First means data is transmitted/received with data bit 0 first, following the start bit. + * @rmtoll CR2 MSBFIRST LL_USART_GetTransferBitOrder + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_BITORDER_LSBFIRST + * @arg @ref LL_USART_BITORDER_MSBFIRST + */ +__STATIC_INLINE uint32_t LL_USART_GetTransferBitOrder(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_MSBFIRST)); +} + +/** + * @brief Enable Auto Baud-Rate Detection + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABREN LL_USART_EnableAutoBaudRate + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableAutoBaudRate(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_ABREN); +} + +/** + * @brief Disable Auto Baud-Rate Detection + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABREN LL_USART_DisableAutoBaudRate + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableAutoBaudRate(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_ABREN); +} + +/** + * @brief Indicate if Auto Baud-Rate Detection mechanism is enabled + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABREN LL_USART_IsEnabledAutoBaud + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledAutoBaud(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_ABREN) == (USART_CR2_ABREN)) ? 1UL : 0UL); +} + +/** + * @brief Set Auto Baud-Rate mode bits + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABRMODE LL_USART_SetAutoBaudRateMode + * @param USARTx USART Instance + * @param AutoBaudRateMode This parameter can be one of the following values: + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_STARTBIT + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_7F_FRAME + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_55_FRAME + * @retval None + */ +__STATIC_INLINE void LL_USART_SetAutoBaudRateMode(USART_TypeDef *USARTx, uint32_t AutoBaudRateMode) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_ABRMODE, AutoBaudRateMode); +} + +/** + * @brief Return Auto Baud-Rate mode + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll CR2 ABRMODE LL_USART_GetAutoBaudRateMode + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_STARTBIT + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_FALLINGEDGE + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_7F_FRAME + * @arg @ref LL_USART_AUTOBAUD_DETECT_ON_55_FRAME + */ +__STATIC_INLINE uint32_t LL_USART_GetAutoBaudRateMode(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ABRMODE)); +} + +/** + * @brief Enable Receiver Timeout + * @rmtoll CR2 RTOEN LL_USART_EnableRxTimeout + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableRxTimeout(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_RTOEN); +} + +/** + * @brief Disable Receiver Timeout + * @rmtoll CR2 RTOEN LL_USART_DisableRxTimeout + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableRxTimeout(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_RTOEN); +} + +/** + * @brief Indicate if Receiver Timeout feature is enabled + * @rmtoll CR2 RTOEN LL_USART_IsEnabledRxTimeout + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledRxTimeout(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_RTOEN) == (USART_CR2_RTOEN)) ? 1UL : 0UL); +} + +/** + * @brief Set Address of the USART node. + * @note This is used in multiprocessor communication during Mute mode or Stop mode, + * for wake up with address mark detection. + * @note 4bits address node is used when 4-bit Address Detection is selected in ADDM7. + * (b7-b4 should be set to 0) + * 8bits address node is used when 7-bit Address Detection is selected in ADDM7. + * (This is used in multiprocessor communication during Mute mode or Stop mode, + * for wake up with 7-bit address mark detection. + * The MSB of the character sent by the transmitter should be equal to 1. + * It may also be used for character detection during normal reception, + * Mute mode inactive (for example, end of block detection in ModBus protocol). + * In this case, the whole received character (8-bit) is compared to the ADD[7:0] + * value and CMF flag is set on match) + * @rmtoll CR2 ADD LL_USART_ConfigNodeAddress\n + * CR2 ADDM7 LL_USART_ConfigNodeAddress + * @param USARTx USART Instance + * @param AddressLen This parameter can be one of the following values: + * @arg @ref LL_USART_ADDRESS_DETECT_4B + * @arg @ref LL_USART_ADDRESS_DETECT_7B + * @param NodeAddress 4 or 7 bit Address of the USART node. + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigNodeAddress(USART_TypeDef *USARTx, uint32_t AddressLen, uint32_t NodeAddress) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_ADD | USART_CR2_ADDM7, + (uint32_t)(AddressLen | (NodeAddress << USART_CR2_ADD_Pos))); +} + +/** + * @brief Return 8 bit Address of the USART node as set in ADD field of CR2. + * @note If 4-bit Address Detection is selected in ADDM7, + * only 4bits (b3-b0) of returned value are relevant (b31-b4 are not relevant) + * If 7-bit Address Detection is selected in ADDM7, + * only 8bits (b7-b0) of returned value are relevant (b31-b8 are not relevant) + * @rmtoll CR2 ADD LL_USART_GetNodeAddress + * @param USARTx USART Instance + * @retval Address of the USART node (Value between Min_Data=0 and Max_Data=255) + */ +__STATIC_INLINE uint32_t LL_USART_GetNodeAddress(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ADD) >> USART_CR2_ADD_Pos); +} + +/** + * @brief Return Length of Node Address used in Address Detection mode (7-bit or 4-bit) + * @rmtoll CR2 ADDM7 LL_USART_GetNodeAddressLen + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_ADDRESS_DETECT_4B + * @arg @ref LL_USART_ADDRESS_DETECT_7B + */ +__STATIC_INLINE uint32_t LL_USART_GetNodeAddressLen(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_ADDM7)); +} + +/** + * @brief Enable RTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_EnableRTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableRTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_RTSE); +} + +/** + * @brief Disable RTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_DisableRTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableRTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_RTSE); +} + +/** + * @brief Enable CTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSE LL_USART_EnableCTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableCTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_CTSE); +} + +/** + * @brief Disable CTS HW Flow Control + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSE LL_USART_DisableCTSHWFlowCtrl + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableCTSHWFlowCtrl(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_CTSE); +} + +/** + * @brief Configure HW Flow Control mode (both CTS and RTS) + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_SetHWFlowCtrl\n + * CR3 CTSE LL_USART_SetHWFlowCtrl + * @param USARTx USART Instance + * @param HardwareFlowControl This parameter can be one of the following values: + * @arg @ref LL_USART_HWCONTROL_NONE + * @arg @ref LL_USART_HWCONTROL_RTS + * @arg @ref LL_USART_HWCONTROL_CTS + * @arg @ref LL_USART_HWCONTROL_RTS_CTS + * @retval None + */ +__STATIC_INLINE void LL_USART_SetHWFlowCtrl(USART_TypeDef *USARTx, uint32_t HardwareFlowControl) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_RTSE | USART_CR3_CTSE, HardwareFlowControl); +} + +/** + * @brief Return HW Flow Control configuration (both CTS and RTS) + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 RTSE LL_USART_GetHWFlowCtrl\n + * CR3 CTSE LL_USART_GetHWFlowCtrl + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_HWCONTROL_NONE + * @arg @ref LL_USART_HWCONTROL_RTS + * @arg @ref LL_USART_HWCONTROL_CTS + * @arg @ref LL_USART_HWCONTROL_RTS_CTS + */ +__STATIC_INLINE uint32_t LL_USART_GetHWFlowCtrl(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)) ? 1UL : 0UL); +} + +/** + * @brief Enable Overrun detection + * @rmtoll CR3 OVRDIS LL_USART_EnableOverrunDetect + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableOverrunDetect(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_OVRDIS); +} + +/** + * @brief Disable Overrun detection + * @rmtoll CR3 OVRDIS LL_USART_DisableOverrunDetect + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableOverrunDetect(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_OVRDIS); +} + +/** + * @brief Indicate if Overrun detection is enabled + * @rmtoll CR3 OVRDIS LL_USART_IsEnabledOverrunDetect + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledOverrunDetect(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_OVRDIS) != USART_CR3_OVRDIS) ? 1UL : 0UL); +} + +/** + * @brief Select event type for Wake UP Interrupt Flag (WUS[1:0] bits) + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUS LL_USART_SetWKUPType + * @param USARTx USART Instance + * @param Type This parameter can be one of the following values: + * @arg @ref LL_USART_WAKEUP_ON_ADDRESS + * @arg @ref LL_USART_WAKEUP_ON_STARTBIT + * @arg @ref LL_USART_WAKEUP_ON_RXNE + * @retval None + */ +__STATIC_INLINE void LL_USART_SetWKUPType(USART_TypeDef *USARTx, uint32_t Type) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_WUS, Type); +} + +/** + * @brief Return event type for Wake UP Interrupt Flag (WUS[1:0] bits) + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUS LL_USART_GetWKUPType + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_WAKEUP_ON_ADDRESS + * @arg @ref LL_USART_WAKEUP_ON_STARTBIT + * @arg @ref LL_USART_WAKEUP_ON_RXNE + */ +__STATIC_INLINE uint32_t LL_USART_GetWKUPType(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_WUS)); +} + +/** + * @brief Configure USART BRR register for achieving expected Baud Rate value. + * @note Compute and set USARTDIV value in BRR Register (full BRR content) + * according to used Peripheral Clock, Oversampling mode, and expected Baud Rate values + * @note Peripheral clock and Baud rate values provided as function parameters should be valid + * (Baud rate value != 0) + * @note In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. + * @rmtoll BRR BRR LL_USART_SetBaudRate + * @param USARTx USART Instance + * @param PeriphClk Peripheral Clock + @if USART_PRESC_PRESCALER + * @param PrescalerValue This parameter can be one of the following values: + * @arg @ref LL_USART_PRESCALER_DIV1 + * @arg @ref LL_USART_PRESCALER_DIV2 + * @arg @ref LL_USART_PRESCALER_DIV4 + * @arg @ref LL_USART_PRESCALER_DIV6 + * @arg @ref LL_USART_PRESCALER_DIV8 + * @arg @ref LL_USART_PRESCALER_DIV10 + * @arg @ref LL_USART_PRESCALER_DIV12 + * @arg @ref LL_USART_PRESCALER_DIV16 + * @arg @ref LL_USART_PRESCALER_DIV32 + * @arg @ref LL_USART_PRESCALER_DIV64 + * @arg @ref LL_USART_PRESCALER_DIV128 + * @arg @ref LL_USART_PRESCALER_DIV256 + @endif + * @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 + */ +#if defined(USART_PRESC_PRESCALER) +__STATIC_INLINE void LL_USART_SetBaudRate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t PrescalerValue, + uint32_t OverSampling, + uint32_t BaudRate) +#else +__STATIC_INLINE void LL_USART_SetBaudRate(USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t OverSampling, + uint32_t BaudRate) +#endif /* USART_PRESC_PRESCALER */ +{ + uint32_t usartdiv; + uint32_t brrtemp; + +#if defined(USART_PRESC_PRESCALER) + if (PrescalerValue > LL_USART_PRESCALER_DIV256) + { + /* Do not overstep the size of USART_PRESCALER_TAB */ + } + else if (BaudRate == 0U) + { + /* Can Not divide per 0 */ + } + else if (OverSampling == LL_USART_OVERSAMPLING_8) +#else + if (OverSampling == LL_USART_OVERSAMPLING_8) +#endif /* USART_PRESC_PRESCALER */ + { +#if defined(USART_PRESC_PRESCALER) + usartdiv = (uint16_t)(__LL_USART_DIV_SAMPLING8(PeriphClk, (uint8_t)PrescalerValue, BaudRate)); +#else + usartdiv = (uint16_t)(__LL_USART_DIV_SAMPLING8(PeriphClk, BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + brrtemp = usartdiv & 0xFFF0U; + brrtemp |= (uint16_t)((usartdiv & (uint16_t)0x000FU) >> 1U); + USARTx->BRR = brrtemp; + } + else + { +#if defined(USART_PRESC_PRESCALER) + USARTx->BRR = (uint16_t)(__LL_USART_DIV_SAMPLING16(PeriphClk, (uint8_t)PrescalerValue, BaudRate)); +#else + USARTx->BRR = (uint16_t)(__LL_USART_DIV_SAMPLING16(PeriphClk, BaudRate)); +#endif /* USART_PRESC_PRESCALER */ + } +} + +/** + * @brief Return current Baud Rate value, according to USARTDIV present in BRR register + * (full BRR content), and to used Peripheral Clock and Oversampling mode values + * @note In case of non-initialized or invalid value stored in BRR register, value 0 will be returned. + * @note In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. + * @rmtoll BRR BRR LL_USART_GetBaudRate + * @param USARTx USART Instance + * @param PeriphClk Peripheral Clock + @if USART_PRESC_PRESCALER + * @param PrescalerValue This parameter can be one of the following values: + * @arg @ref LL_USART_PRESCALER_DIV1 + * @arg @ref LL_USART_PRESCALER_DIV2 + * @arg @ref LL_USART_PRESCALER_DIV4 + * @arg @ref LL_USART_PRESCALER_DIV6 + * @arg @ref LL_USART_PRESCALER_DIV8 + * @arg @ref LL_USART_PRESCALER_DIV10 + * @arg @ref LL_USART_PRESCALER_DIV12 + * @arg @ref LL_USART_PRESCALER_DIV16 + * @arg @ref LL_USART_PRESCALER_DIV32 + * @arg @ref LL_USART_PRESCALER_DIV64 + * @arg @ref LL_USART_PRESCALER_DIV128 + * @arg @ref LL_USART_PRESCALER_DIV256 + @endif + * @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 + */ +#if defined(USART_PRESC_PRESCALER) +__STATIC_INLINE uint32_t LL_USART_GetBaudRate(const USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t PrescalerValue, + uint32_t OverSampling) +#else +__STATIC_INLINE uint32_t LL_USART_GetBaudRate(const USART_TypeDef *USARTx, uint32_t PeriphClk, uint32_t OverSampling) +#endif /* USART_PRESC_PRESCALER */ +{ + uint32_t usartdiv; + uint32_t brrresult = 0x0U; +#if defined(USART_PRESC_PRESCALER) + uint32_t periphclkpresc = (uint32_t)(PeriphClk / (USART_PRESCALER_TAB[(uint8_t)PrescalerValue])); +#endif /* USART_PRESC_PRESCALER */ + + usartdiv = USARTx->BRR; + + if (usartdiv == 0U) + { + /* Do not perform a division by 0 */ + } + else if (OverSampling == LL_USART_OVERSAMPLING_8) + { + usartdiv = (uint16_t)((usartdiv & 0xFFF0U) | ((usartdiv & 0x0007U) << 1U)) ; + if (usartdiv != 0U) + { +#if defined(USART_PRESC_PRESCALER) + brrresult = (periphclkpresc * 2U) / usartdiv; +#else + brrresult = (PeriphClk * 2U) / usartdiv; +#endif /* USART_PRESC_PRESCALER */ + } + } + else + { + if ((usartdiv & 0xFFFFU) != 0U) + { +#if defined(USART_PRESC_PRESCALER) + brrresult = periphclkpresc / usartdiv; +#else + brrresult = PeriphClk / usartdiv; +#endif /* USART_PRESC_PRESCALER */ + } + } + return (brrresult); +} + +/** + * @brief Set Receiver Time Out Value (expressed in nb of bits duration) + * @rmtoll RTOR RTO LL_USART_SetRxTimeout + * @param USARTx USART Instance + * @param Timeout Value between Min_Data=0x00 and Max_Data=0x00FFFFFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetRxTimeout(USART_TypeDef *USARTx, uint32_t Timeout) +{ + MODIFY_REG(USARTx->RTOR, USART_RTOR_RTO, Timeout); +} + +/** + * @brief Get Receiver Time Out Value (expressed in nb of bits duration) + * @rmtoll RTOR RTO LL_USART_GetRxTimeout + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x00FFFFFF + */ +__STATIC_INLINE uint32_t LL_USART_GetRxTimeout(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->RTOR, USART_RTOR_RTO)); +} + +/** + * @brief Set Block Length value in reception + * @rmtoll RTOR BLEN LL_USART_SetBlockLength + * @param USARTx USART Instance + * @param BlockLength Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetBlockLength(USART_TypeDef *USARTx, uint32_t BlockLength) +{ + MODIFY_REG(USARTx->RTOR, USART_RTOR_BLEN, BlockLength << USART_RTOR_BLEN_Pos); +} + +/** + * @brief Get Block Length value in reception + * @rmtoll RTOR BLEN LL_USART_GetBlockLength + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_USART_GetBlockLength(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->RTOR, USART_RTOR_BLEN) >> USART_RTOR_BLEN_Pos); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_IRDA Configuration functions related to Irda feature + * @{ + */ + +/** + * @brief Enable IrDA mode + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IREN LL_USART_EnableIrda + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIrda(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_IREN); +} + +/** + * @brief Disable IrDA mode + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IREN LL_USART_DisableIrda + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIrda(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_IREN); +} + +/** + * @brief Indicate if IrDA mode is enabled + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IREN LL_USART_IsEnabledIrda + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIrda(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_IREN) == (USART_CR3_IREN)) ? 1UL : 0UL); +} + +/** + * @brief Configure IrDA Power Mode (Normal or Low Power) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IRLP LL_USART_SetIrdaPowerMode + * @param USARTx USART Instance + * @param PowerMode This parameter can be one of the following values: + * @arg @ref LL_USART_IRDA_POWER_NORMAL + * @arg @ref LL_USART_IRDA_POWER_LOW + * @retval None + */ +__STATIC_INLINE void LL_USART_SetIrdaPowerMode(USART_TypeDef *USARTx, uint32_t PowerMode) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_IRLP, PowerMode); +} + +/** + * @brief Retrieve IrDA Power Mode configuration (Normal or Low Power) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll CR3 IRLP LL_USART_GetIrdaPowerMode + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_IRDA_POWER_NORMAL + * @arg @ref LL_USART_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_USART_GetIrdaPowerMode(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_IRLP)); +} + +/** + * @brief Set Irda prescaler value, used for dividing the USART clock source + * to achieve the Irda Low Power frequency (8 bits value) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_SetIrdaPrescaler + * @param USARTx USART Instance + * @param PrescalerValue Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetIrdaPrescaler(USART_TypeDef *USARTx, uint32_t PrescalerValue) +{ + MODIFY_REG(USARTx->GTPR, USART_GTPR_PSC, (uint16_t)PrescalerValue); +} + +/** + * @brief Return Irda prescaler value, used for dividing the USART clock source + * to achieve the Irda Low Power frequency (8 bits value) + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_GetIrdaPrescaler + * @param USARTx USART Instance + * @retval Irda prescaler value (Value between Min_Data=0x00 and Max_Data=0xFF) + */ +__STATIC_INLINE uint32_t LL_USART_GetIrdaPrescaler(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_PSC)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_Smartcard Configuration functions related to Smartcard feature + * @{ + */ + +/** + * @brief Enable Smartcard NACK transmission + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 NACK LL_USART_EnableSmartcardNACK + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSmartcardNACK(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_NACK); +} + +/** + * @brief Disable Smartcard NACK transmission + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 NACK LL_USART_DisableSmartcardNACK + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSmartcardNACK(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_NACK); +} + +/** + * @brief Indicate if Smartcard NACK transmission is enabled + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 NACK LL_USART_IsEnabledSmartcardNACK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSmartcardNACK(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_NACK) == (USART_CR3_NACK)) ? 1UL : 0UL); +} + +/** + * @brief Enable Smartcard mode + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCEN LL_USART_EnableSmartcard + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSmartcard(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_SCEN); +} + +/** + * @brief Disable Smartcard mode + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCEN LL_USART_DisableSmartcard + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSmartcard(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_SCEN); +} + +/** + * @brief Indicate if Smartcard mode is enabled + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCEN LL_USART_IsEnabledSmartcard + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSmartcard(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_SCEN) == (USART_CR3_SCEN)) ? 1UL : 0UL); +} + +/** + * @brief Set Smartcard Auto-Retry Count value (SCARCNT[2:0] bits) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @note This bit-field specifies the number of retries in transmit and receive, in Smartcard mode. + * In transmission mode, it specifies the number of automatic retransmission retries, before + * generating a transmission error (FE bit set). + * In reception mode, it specifies the number or erroneous reception trials, before generating a + * reception error (RXNE and PE bits set) + * @rmtoll CR3 SCARCNT LL_USART_SetSmartcardAutoRetryCount + * @param USARTx USART Instance + * @param AutoRetryCount Value between Min_Data=0 and Max_Data=7 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetSmartcardAutoRetryCount(USART_TypeDef *USARTx, uint32_t AutoRetryCount) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_SCARCNT, AutoRetryCount << USART_CR3_SCARCNT_Pos); +} + +/** + * @brief Return Smartcard Auto-Retry Count value (SCARCNT[2:0] bits) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 SCARCNT LL_USART_GetSmartcardAutoRetryCount + * @param USARTx USART Instance + * @retval Smartcard Auto-Retry Count value (Value between Min_Data=0 and Max_Data=7) + */ +__STATIC_INLINE uint32_t LL_USART_GetSmartcardAutoRetryCount(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_SCARCNT) >> USART_CR3_SCARCNT_Pos); +} + +/** + * @brief Set Smartcard prescaler value, used for dividing the USART clock + * source to provide the SMARTCARD Clock (5 bits value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_SetSmartcardPrescaler + * @param USARTx USART Instance + * @param PrescalerValue Value between Min_Data=0 and Max_Data=31 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetSmartcardPrescaler(USART_TypeDef *USARTx, uint32_t PrescalerValue) +{ + MODIFY_REG(USARTx->GTPR, USART_GTPR_PSC, (uint16_t)PrescalerValue); +} + +/** + * @brief Return Smartcard prescaler value, used for dividing the USART clock + * source to provide the SMARTCARD Clock (5 bits value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR PSC LL_USART_GetSmartcardPrescaler + * @param USARTx USART Instance + * @retval Smartcard prescaler value (Value between Min_Data=0 and Max_Data=31) + */ +__STATIC_INLINE uint32_t LL_USART_GetSmartcardPrescaler(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_PSC)); +} + +/** + * @brief Set Smartcard Guard time value, expressed in nb of baud clocks periods + * (GT[7:0] bits : Guard time value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR GT LL_USART_SetSmartcardGuardTime + * @param USARTx USART Instance + * @param GuardTime Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_SetSmartcardGuardTime(USART_TypeDef *USARTx, uint32_t GuardTime) +{ + MODIFY_REG(USARTx->GTPR, USART_GTPR_GT, (uint16_t)(GuardTime << USART_GTPR_GT_Pos)); +} + +/** + * @brief Return Smartcard Guard time value, expressed in nb of baud clocks periods + * (GT[7:0] bits : Guard time value) + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll GTPR GT LL_USART_GetSmartcardGuardTime + * @param USARTx USART Instance + * @retval Smartcard Guard time value (Value between Min_Data=0x00 and Max_Data=0xFF) + */ +__STATIC_INLINE uint32_t LL_USART_GetSmartcardGuardTime(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->GTPR, USART_GTPR_GT) >> USART_GTPR_GT_Pos); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_HalfDuplex Configuration functions related to Half Duplex feature + * @{ + */ + +/** + * @brief Enable Single Wire Half-Duplex mode + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @rmtoll CR3 HDSEL LL_USART_EnableHalfDuplex + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableHalfDuplex(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_HDSEL); +} + +/** + * @brief Disable Single Wire Half-Duplex mode + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @rmtoll CR3 HDSEL LL_USART_DisableHalfDuplex + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableHalfDuplex(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_HDSEL); +} + +/** + * @brief Indicate if Single Wire Half-Duplex mode is enabled + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @rmtoll CR3 HDSEL LL_USART_IsEnabledHalfDuplex + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledHalfDuplex(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_HDSEL) == (USART_CR3_HDSEL)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#if defined(USART_CR2_SLVEN) +/** @defgroup USART_LL_EF_Configuration_SPI_SLAVE Configuration functions related to SPI Slave feature + * @{ + */ +/** + * @brief Enable SPI Synchronous Slave mode + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @rmtoll CR2 SLVEN LL_USART_EnableSPISlave + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSPISlave(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_SLVEN); +} + +/** + * @brief Disable SPI Synchronous Slave mode + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @rmtoll CR2 SLVEN LL_USART_DisableSPISlave + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSPISlave(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_SLVEN); +} + +/** + * @brief Indicate if SPI Synchronous Slave mode is enabled + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @rmtoll CR2 SLVEN LL_USART_IsEnabledSPISlave + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSPISlave(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_SLVEN) == (USART_CR2_SLVEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable SPI Slave Selection using NSS input pin + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @note SPI Slave Selection depends on NSS input pin + * (The slave is selected when NSS is low and deselected when NSS is high). + * @rmtoll CR2 DIS_NSS LL_USART_EnableSPISlaveSelect + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableSPISlaveSelect(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_DIS_NSS); +} + +/** + * @brief Disable SPI Slave Selection using NSS input pin + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @note SPI Slave will be always selected and NSS input pin will be ignored. + * @rmtoll CR2 DIS_NSS LL_USART_DisableSPISlaveSelect + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableSPISlaveSelect(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_DIS_NSS); +} + +/** + * @brief Indicate if SPI Slave Selection depends on NSS input pin + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @rmtoll CR2 DIS_NSS LL_USART_IsEnabledSPISlaveSelect + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledSPISlaveSelect(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_DIS_NSS) != (USART_CR2_DIS_NSS)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#endif /* USART_CR2_SLVEN */ +/** @defgroup USART_LL_EF_Configuration_LIN Configuration functions related to LIN feature + * @{ + */ + +/** + * @brief Set LIN Break Detection Length + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDL LL_USART_SetLINBrkDetectionLen + * @param USARTx USART Instance + * @param LINBDLength This parameter can be one of the following values: + * @arg @ref LL_USART_LINBREAK_DETECT_10B + * @arg @ref LL_USART_LINBREAK_DETECT_11B + * @retval None + */ +__STATIC_INLINE void LL_USART_SetLINBrkDetectionLen(USART_TypeDef *USARTx, uint32_t LINBDLength) +{ + MODIFY_REG(USARTx->CR2, USART_CR2_LBDL, LINBDLength); +} + +/** + * @brief Return LIN Break Detection Length + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDL LL_USART_GetLINBrkDetectionLen + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_LINBREAK_DETECT_10B + * @arg @ref LL_USART_LINBREAK_DETECT_11B + */ +__STATIC_INLINE uint32_t LL_USART_GetLINBrkDetectionLen(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR2, USART_CR2_LBDL)); +} + +/** + * @brief Enable LIN mode + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LINEN LL_USART_EnableLIN + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableLIN(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_LINEN); +} + +/** + * @brief Disable LIN mode + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LINEN LL_USART_DisableLIN + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableLIN(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_LINEN); +} + +/** + * @brief Indicate if LIN mode is enabled + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LINEN LL_USART_IsEnabledLIN + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledLIN(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_LINEN) == (USART_CR2_LINEN)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_DE Configuration functions related to Driver Enable feature + * @{ + */ + +/** + * @brief Set DEDT (Driver Enable De-Assertion Time), Time value expressed on 5 bits ([4:0] bits). + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEDT LL_USART_SetDEDeassertionTime + * @param USARTx USART Instance + * @param Time Value between Min_Data=0 and Max_Data=31 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDEDeassertionTime(USART_TypeDef *USARTx, uint32_t Time) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_DEDT, Time << USART_CR1_DEDT_Pos); +} + +/** + * @brief Return DEDT (Driver Enable De-Assertion Time) + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEDT LL_USART_GetDEDeassertionTime + * @param USARTx USART Instance + * @retval Time value expressed on 5 bits ([4:0] bits) : Value between Min_Data=0 and Max_Data=31 + */ +__STATIC_INLINE uint32_t LL_USART_GetDEDeassertionTime(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_DEDT) >> USART_CR1_DEDT_Pos); +} + +/** + * @brief Set DEAT (Driver Enable Assertion Time), Time value expressed on 5 bits ([4:0] bits). + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEAT LL_USART_SetDEAssertionTime + * @param USARTx USART Instance + * @param Time Value between Min_Data=0 and Max_Data=31 + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDEAssertionTime(USART_TypeDef *USARTx, uint32_t Time) +{ + MODIFY_REG(USARTx->CR1, USART_CR1_DEAT, Time << USART_CR1_DEAT_Pos); +} + +/** + * @brief Return DEAT (Driver Enable Assertion Time) + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR1 DEAT LL_USART_GetDEAssertionTime + * @param USARTx USART Instance + * @retval Time value expressed on 5 bits ([4:0] bits) : Value between Min_Data=0 and Max_Data=31 + */ +__STATIC_INLINE uint32_t LL_USART_GetDEAssertionTime(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR1, USART_CR1_DEAT) >> USART_CR1_DEAT_Pos); +} + +/** + * @brief Enable Driver Enable (DE) Mode + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEM LL_USART_EnableDEMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDEMode(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_DEM); +} + +/** + * @brief Disable Driver Enable (DE) Mode + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEM LL_USART_DisableDEMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDEMode(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_DEM); +} + +/** + * @brief Indicate if Driver Enable (DE) Mode is enabled + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEM LL_USART_IsEnabledDEMode + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDEMode(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DEM) == (USART_CR3_DEM)) ? 1UL : 0UL); +} + +/** + * @brief Select Driver Enable Polarity + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEP LL_USART_SetDESignalPolarity + * @param USARTx USART Instance + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_USART_DE_POLARITY_HIGH + * @arg @ref LL_USART_DE_POLARITY_LOW + * @retval None + */ +__STATIC_INLINE void LL_USART_SetDESignalPolarity(USART_TypeDef *USARTx, uint32_t Polarity) +{ + MODIFY_REG(USARTx->CR3, USART_CR3_DEP, Polarity); +} + +/** + * @brief Return Driver Enable Polarity + * @note Macro IS_UART_DRIVER_ENABLE_INSTANCE(USARTx) can be used to check whether or not + * Driver Enable feature is supported by the USARTx instance. + * @rmtoll CR3 DEP LL_USART_GetDESignalPolarity + * @param USARTx USART Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_USART_DE_POLARITY_HIGH + * @arg @ref LL_USART_DE_POLARITY_LOW + */ +__STATIC_INLINE uint32_t LL_USART_GetDESignalPolarity(const USART_TypeDef *USARTx) +{ + return (uint32_t)(READ_BIT(USARTx->CR3, USART_CR3_DEP)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_AdvancedConfiguration Advanced Configurations services + * @{ + */ + +/** + * @brief Perform basic configuration of USART for enabling use in Asynchronous Mode (UART) + * @note In UART mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - CLKEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * @note Other remaining configurations items related to Asynchronous Mode + * (as Baud Rate, Word length, Parity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigAsyncMode\n + * CR2 CLKEN LL_USART_ConfigAsyncMode\n + * CR3 SCEN LL_USART_ConfigAsyncMode\n + * CR3 IREN LL_USART_ConfigAsyncMode\n + * CR3 HDSEL LL_USART_ConfigAsyncMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigAsyncMode(USART_TypeDef *USARTx) +{ + /* In Asynchronous mode, the following bits must be kept cleared: + - LINEN, CLKEN bits in the USART_CR2 register, + - SCEN, IREN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_IREN | USART_CR3_HDSEL)); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Synchronous Mode + * @note In Synchronous mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also sets the USART in Synchronous mode. + * @note Macro IS_USART_INSTANCE(USARTx) can be used to check whether or not + * Synchronous mode is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Set CLKEN in CR2 using @ref LL_USART_EnableSCLKOutput() function + * @note Other remaining configurations items related to Synchronous Mode + * (as Baud Rate, Word length, Parity, Clock Polarity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigSyncMode\n + * CR2 CLKEN LL_USART_ConfigSyncMode\n + * CR3 SCEN LL_USART_ConfigSyncMode\n + * CR3 IREN LL_USART_ConfigSyncMode\n + * CR3 HDSEL LL_USART_ConfigSyncMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigSyncMode(USART_TypeDef *USARTx) +{ + /* In Synchronous mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register, + - SCEN, IREN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_IREN | USART_CR3_HDSEL)); + /* set the UART/USART in Synchronous mode */ + SET_BIT(USARTx->CR2, USART_CR2_CLKEN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in LIN Mode + * @note In LIN mode, the following bits must be kept cleared: + * - STOP and CLKEN bits in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also set the UART/USART in LIN mode. + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear STOP in CR2 using @ref LL_USART_SetStopBitsLength() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Set LINEN in CR2 using @ref LL_USART_EnableLIN() function + * @note Other remaining configurations items related to LIN Mode + * (as Baud Rate, Word length, LIN Break Detection Length, ...) should be set using + * dedicated functions + * @rmtoll CR2 CLKEN LL_USART_ConfigLINMode\n + * CR2 STOP LL_USART_ConfigLINMode\n + * CR2 LINEN LL_USART_ConfigLINMode\n + * CR3 IREN LL_USART_ConfigLINMode\n + * CR3 SCEN LL_USART_ConfigLINMode\n + * CR3 HDSEL LL_USART_ConfigLINMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigLINMode(USART_TypeDef *USARTx) +{ + /* In LIN mode, the following bits must be kept cleared: + - STOP and CLKEN bits in the USART_CR2 register, + - IREN, SCEN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_CLKEN | USART_CR2_STOP)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_IREN | USART_CR3_SCEN | USART_CR3_HDSEL)); + /* Set the UART/USART in LIN mode */ + SET_BIT(USARTx->CR2, USART_CR2_LINEN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Half Duplex Mode + * @note In Half Duplex mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - CLKEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * This function also sets the UART/USART in Half Duplex mode. + * @note Macro IS_UART_HALFDUPLEX_INSTANCE(USARTx) can be used to check whether or not + * Half-Duplex mode is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Set HDSEL in CR3 using @ref LL_USART_EnableHalfDuplex() function + * @note Other remaining configurations items related to Half Duplex Mode + * (as Baud Rate, Word length, Parity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigHalfDuplexMode\n + * CR2 CLKEN LL_USART_ConfigHalfDuplexMode\n + * CR3 HDSEL LL_USART_ConfigHalfDuplexMode\n + * CR3 SCEN LL_USART_ConfigHalfDuplexMode\n + * CR3 IREN LL_USART_ConfigHalfDuplexMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigHalfDuplexMode(USART_TypeDef *USARTx) +{ + /* In Half Duplex mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - SCEN and IREN bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_IREN)); + /* set the UART/USART in Half Duplex mode */ + SET_BIT(USARTx->CR3, USART_CR3_HDSEL); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Smartcard Mode + * @note In Smartcard mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also configures Stop bits to 1.5 bits and + * sets the USART in Smartcard mode (SCEN bit). + * Clock Output is also enabled (CLKEN). + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Configure STOP in CR2 using @ref LL_USART_SetStopBitsLength() function + * - Set CLKEN in CR2 using @ref LL_USART_EnableSCLKOutput() function + * - Set SCEN in CR3 using @ref LL_USART_EnableSmartcard() function + * @note Other remaining configurations items related to Smartcard Mode + * (as Baud Rate, Word length, Parity, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigSmartcardMode\n + * CR2 STOP LL_USART_ConfigSmartcardMode\n + * CR2 CLKEN LL_USART_ConfigSmartcardMode\n + * CR3 HDSEL LL_USART_ConfigSmartcardMode\n + * CR3 SCEN LL_USART_ConfigSmartcardMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigSmartcardMode(USART_TypeDef *USARTx) +{ + /* In Smartcard mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register, + - IREN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_IREN | USART_CR3_HDSEL)); + /* Configure Stop bits to 1.5 bits */ + /* Synchronous mode is activated by default */ + SET_BIT(USARTx->CR2, (USART_CR2_STOP_0 | USART_CR2_STOP_1 | USART_CR2_CLKEN)); + /* set the UART/USART in Smartcard mode */ + SET_BIT(USARTx->CR3, USART_CR3_SCEN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Irda Mode + * @note In IRDA mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - STOP and CLKEN bits in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * This function also sets the UART/USART in IRDA mode (IREN bit). + * @note Macro IS_IRDA_INSTANCE(USARTx) can be used to check whether or not + * IrDA feature is supported by the USARTx instance. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * - Configure STOP in CR2 using @ref LL_USART_SetStopBitsLength() function + * - Set IREN in CR3 using @ref LL_USART_EnableIrda() function + * @note Other remaining configurations items related to Irda Mode + * (as Baud Rate, Word length, Power mode, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigIrdaMode\n + * CR2 CLKEN LL_USART_ConfigIrdaMode\n + * CR2 STOP LL_USART_ConfigIrdaMode\n + * CR3 SCEN LL_USART_ConfigIrdaMode\n + * CR3 HDSEL LL_USART_ConfigIrdaMode\n + * CR3 IREN LL_USART_ConfigIrdaMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigIrdaMode(USART_TypeDef *USARTx) +{ + /* In IRDA mode, the following bits must be kept cleared: + - LINEN, STOP and CLKEN bits in the USART_CR2 register, + - SCEN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN | USART_CR2_STOP)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL)); + /* set the UART/USART in IRDA mode */ + SET_BIT(USARTx->CR3, USART_CR3_IREN); +} + +/** + * @brief Perform basic configuration of USART for enabling use in Multi processor Mode + * (several USARTs connected in a network, one of the USARTs can be the master, + * its TX output connected to the RX inputs of the other slaves USARTs). + * @note In MultiProcessor mode, the following bits must be kept cleared: + * - LINEN bit in the USART_CR2 register, + * - CLKEN bit in the USART_CR2 register, + * - SCEN bit in the USART_CR3 register, + * - IREN bit in the USART_CR3 register, + * - HDSEL bit in the USART_CR3 register. + * @note Call of this function is equivalent to following function call sequence : + * - Clear LINEN in CR2 using @ref LL_USART_DisableLIN() function + * - Clear CLKEN in CR2 using @ref LL_USART_DisableSCLKOutput() function + * - Clear SCEN in CR3 using @ref LL_USART_DisableSmartcard() function + * - Clear IREN in CR3 using @ref LL_USART_DisableIrda() function + * - Clear HDSEL in CR3 using @ref LL_USART_DisableHalfDuplex() function + * @note Other remaining configurations items related to Multi processor Mode + * (as Baud Rate, Wake Up Method, Node address, ...) should be set using + * dedicated functions + * @rmtoll CR2 LINEN LL_USART_ConfigMultiProcessMode\n + * CR2 CLKEN LL_USART_ConfigMultiProcessMode\n + * CR3 SCEN LL_USART_ConfigMultiProcessMode\n + * CR3 HDSEL LL_USART_ConfigMultiProcessMode\n + * CR3 IREN LL_USART_ConfigMultiProcessMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ConfigMultiProcessMode(USART_TypeDef *USARTx) +{ + /* In Multi Processor mode, the following bits must be kept cleared: + - LINEN and CLKEN bits in the USART_CR2 register, + - IREN, SCEN and HDSEL bits in the USART_CR3 register. + */ + CLEAR_BIT(USARTx->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(USARTx->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Check if the USART Parity Error Flag is set or not + * @rmtoll ISR PE LL_USART_IsActiveFlag_PE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_PE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_PE) == (USART_ISR_PE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Framing Error Flag is set or not + * @rmtoll ISR FE LL_USART_IsActiveFlag_FE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_FE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_FE) == (USART_ISR_FE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Noise error detected Flag is set or not + * @rmtoll ISR NE LL_USART_IsActiveFlag_NE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_NE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_NE) == (USART_ISR_NE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART OverRun Error Flag is set or not + * @rmtoll ISR ORE LL_USART_IsActiveFlag_ORE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ORE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_ORE) == (USART_ISR_ORE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART IDLE line detected Flag is set or not + * @rmtoll ISR IDLE LL_USART_IsActiveFlag_IDLE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_IDLE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_IDLE) == (USART_ISR_IDLE)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_IsActiveFlag_RXNE LL_USART_IsActiveFlag_RXNE_RXFNE /* Redefinition for legacy purpose */ + +/** + * @brief Check if the USART Read Data Register or USART RX FIFO Not Empty Flag is set or not + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ISR RXNE_RXFNE LL_USART_IsActiveFlag_RXNE_RXFNE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RXNE_RXFNE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RXNE_RXFNE) == (USART_ISR_RXNE_RXFNE)) ? 1UL : 0UL); +} + +#else +/** + * @brief Check if the USART Read Data Register Not Empty Flag is set or not + * @rmtoll ISR RXNE LL_USART_IsActiveFlag_RXNE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RXNE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RXNE) == (USART_ISR_RXNE)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Check if the USART Transmission Complete Flag is set or not + * @rmtoll ISR TC LL_USART_IsActiveFlag_TC + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TC(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TC) == (USART_ISR_TC)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_IsActiveFlag_TXE LL_USART_IsActiveFlag_TXE_TXFNF /* Redefinition for legacy purpose */ + +/** + * @brief Check if the USART Transmit Data Register Empty or USART TX FIFO Not Full Flag is set or not + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ISR TXE_TXFNF LL_USART_IsActiveFlag_TXE_TXFNF + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TXE_TXFNF(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TXE_TXFNF) == (USART_ISR_TXE_TXFNF)) ? 1UL : 0UL); +} + +#else +/** + * @brief Check if the USART Transmit Data Register Empty Flag is set or not + * @rmtoll ISR TXE LL_USART_IsActiveFlag_TXE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TXE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TXE) == (USART_ISR_TXE)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Check if the USART LIN Break Detection Flag is set or not + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll ISR LBDF LL_USART_IsActiveFlag_LBD + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_LBD(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_LBDF) == (USART_ISR_LBDF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART CTS interrupt Flag is set or not + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll ISR CTSIF LL_USART_IsActiveFlag_nCTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_nCTS(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_CTSIF) == (USART_ISR_CTSIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART CTS Flag is set or not + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll ISR CTS LL_USART_IsActiveFlag_CTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_CTS(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_CTS) == (USART_ISR_CTS)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receiver Time Out Flag is set or not + * @rmtoll ISR RTOF LL_USART_IsActiveFlag_RTO + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RTO(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RTOF) == (USART_ISR_RTOF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART End Of Block Flag is set or not + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll ISR EOBF LL_USART_IsActiveFlag_EOB + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_EOB(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_EOBF) == (USART_ISR_EOBF)) ? 1UL : 0UL); +} + +#if defined(USART_CR2_SLVEN) +/** + * @brief Check if the SPI Slave Underrun error flag is set or not + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @rmtoll ISR UDR LL_USART_IsActiveFlag_UDR + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_UDR(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_UDR) == (USART_ISR_UDR)) ? 1UL : 0UL); +} + +#endif /* USART_CR2_SLVEN */ +/** + * @brief Check if the USART Auto-Baud Rate Error Flag is set or not + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll ISR ABRE LL_USART_IsActiveFlag_ABRE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ABRE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_ABRE) == (USART_ISR_ABRE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Auto-Baud Rate Flag is set or not + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll ISR ABRF LL_USART_IsActiveFlag_ABR + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_ABR(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_ABRF) == (USART_ISR_ABRF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Busy Flag is set or not + * @rmtoll ISR BUSY LL_USART_IsActiveFlag_BUSY + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_BUSY(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_BUSY) == (USART_ISR_BUSY)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Character Match Flag is set or not + * @rmtoll ISR CMF LL_USART_IsActiveFlag_CM + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_CM(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_CMF) == (USART_ISR_CMF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Send Break Flag is set or not + * @rmtoll ISR SBKF LL_USART_IsActiveFlag_SBK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_SBK(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_SBKF) == (USART_ISR_SBKF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receive Wake Up from mute mode Flag is set or not + * @rmtoll ISR RWU LL_USART_IsActiveFlag_RWU + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RWU(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RWU) == (USART_ISR_RWU)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Wake Up from stop mode Flag is set or not + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll ISR WUF LL_USART_IsActiveFlag_WKUP + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_WKUP(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_WUF) == (USART_ISR_WUF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Transmit Enable Acknowledge Flag is set or not + * @rmtoll ISR TEACK LL_USART_IsActiveFlag_TEACK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TEACK(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TEACK) == (USART_ISR_TEACK)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receive Enable Acknowledge Flag is set or not + * @rmtoll ISR REACK LL_USART_IsActiveFlag_REACK + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_REACK(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_REACK) == (USART_ISR_REACK)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Check if the USART TX FIFO Empty Flag is set or not + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ISR TXFE LL_USART_IsActiveFlag_TXFE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TXFE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TXFE) == (USART_ISR_TXFE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART RX FIFO Full Flag is set or not + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ISR RXFF LL_USART_IsActiveFlag_RXFF + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RXFF(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RXFF) == (USART_ISR_RXFF)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Check if the Smartcard Transmission Complete Before Guard Time Flag is set or not + * @rmtoll ISR TCBGT LL_USART_IsActiveFlag_TCBGT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TCBGT(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TCBGT) == (USART_ISR_TCBGT)) ? 1UL : 0UL); +} + +#endif /* USART_TCBGT_SUPPORT */ +#if defined(USART_CR1_FIFOEN) +/** + * @brief Check if the USART TX FIFO Threshold Flag is set or not + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ISR TXFT LL_USART_IsActiveFlag_TXFT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_TXFT(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_TXFT) == (USART_ISR_TXFT)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART RX FIFO Threshold Flag is set or not + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ISR RXFT LL_USART_IsActiveFlag_RXFT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsActiveFlag_RXFT(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->ISR, USART_ISR_RXFT) == (USART_ISR_RXFT)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Clear Parity Error Flag + * @rmtoll ICR PECF LL_USART_ClearFlag_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_PE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_PECF); +} + +/** + * @brief Clear Framing Error Flag + * @rmtoll ICR FECF LL_USART_ClearFlag_FE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_FE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_FECF); +} + +/** + * @brief Clear Noise Error detected Flag + * @rmtoll ICR NECF LL_USART_ClearFlag_NE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_NE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_NECF); +} + +/** + * @brief Clear OverRun Error Flag + * @rmtoll ICR ORECF LL_USART_ClearFlag_ORE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_ORE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_ORECF); +} + +/** + * @brief Clear IDLE line detected Flag + * @rmtoll ICR IDLECF LL_USART_ClearFlag_IDLE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_IDLE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_IDLECF); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Clear TX FIFO Empty Flag + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll ICR TXFECF LL_USART_ClearFlag_TXFE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_TXFE(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_TXFECF); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Clear Transmission Complete Flag + * @rmtoll ICR TCCF LL_USART_ClearFlag_TC + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_TC(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_TCCF); +} + +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Clear Smartcard Transmission Complete Before Guard Time Flag + * @rmtoll ICR TCBGTCF LL_USART_ClearFlag_TCBGT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_TCBGT(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_TCBGTCF); +} +#endif /* USART_TCBGT_SUPPORT */ + +/** + * @brief Clear LIN Break Detection Flag + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll ICR LBDCF LL_USART_ClearFlag_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_LBD(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_LBDCF); +} + +/** + * @brief Clear CTS Interrupt Flag + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll ICR CTSCF LL_USART_ClearFlag_nCTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_nCTS(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_CTSCF); +} + +/** + * @brief Clear Receiver Time Out Flag + * @rmtoll ICR RTOCF LL_USART_ClearFlag_RTO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_RTO(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_RTOCF); +} + +/** + * @brief Clear End Of Block Flag + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll ICR EOBCF LL_USART_ClearFlag_EOB + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_EOB(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_EOBCF); +} + +#if defined(USART_CR2_SLVEN) +/** + * @brief Clear SPI Slave Underrun Flag + * @note Macro IS_UART_SPI_SLAVE_INSTANCE(USARTx) can be used to check whether or not + * SPI Slave mode feature is supported by the USARTx instance. + * @rmtoll ICR UDRCF LL_USART_ClearFlag_UDR + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_UDR(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_UDRCF); +} + +#endif /* USART_CR2_SLVEN */ +/** + * @brief Clear Character Match Flag + * @rmtoll ICR CMCF LL_USART_ClearFlag_CM + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_CM(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_CMCF); +} + +/** + * @brief Clear Wake Up from stop mode Flag + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll ICR WUCF LL_USART_ClearFlag_WKUP + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_ClearFlag_WKUP(USART_TypeDef *USARTx) +{ + WRITE_REG(USARTx->ICR, USART_ICR_WUCF); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable IDLE Interrupt + * @rmtoll CR1 IDLEIE LL_USART_EnableIT_IDLE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_IDLE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_IDLEIE); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_EnableIT_RXNE LL_USART_EnableIT_RXNE_RXFNE /* Redefinition for legacy purpose */ + +/** + * @brief Enable RX Not Empty and RX FIFO Not Empty Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 RXNEIE_RXFNEIE LL_USART_EnableIT_RXNE_RXFNE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_RXNE_RXFNE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RXNEIE_RXFNEIE); +} + +#else +/** + * @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); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @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); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_EnableIT_TXE LL_USART_EnableIT_TXE_TXFNF /* Redefinition for legacy purpose */ + +/** + * @brief Enable TX Empty and TX FIFO Not Full Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 TXEIE_TXFNFIE LL_USART_EnableIT_TXE_TXFNF + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TXE_TXFNF(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_TXEIE_TXFNFIE); +} + +#else +/** + * @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); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Enable Parity Error Interrupt + * @rmtoll CR1 PEIE LL_USART_EnableIT_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_PE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_PEIE); +} + +/** + * @brief Enable Character Match Interrupt + * @rmtoll CR1 CMIE LL_USART_EnableIT_CM + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_CM(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_CMIE); +} + +/** + * @brief Enable Receiver Timeout Interrupt + * @rmtoll CR1 RTOIE LL_USART_EnableIT_RTO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_RTO(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RTOIE); +} + +/** + * @brief Enable End Of Block Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR1 EOBIE LL_USART_EnableIT_EOB + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_EOB(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_EOBIE); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Enable TX FIFO Empty Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 TXFEIE LL_USART_EnableIT_TXFE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TXFE(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_TXFEIE); +} + +/** + * @brief Enable RX FIFO Full Interrupt + * @rmtoll CR1 RXFFIE LL_USART_EnableIT_RXFF + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_RXFF(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR1, USART_CR1_RXFFIE); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Enable LIN Break Detection Interrupt + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDIE LL_USART_EnableIT_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_LBD(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR2, USART_CR2_LBDIE); +} + +/** + * @brief Enable Error Interrupt + * @note When set, Error Interrupt Enable Bit is enabling interrupt generation in case of a framing + * error, overrun error or noise flag (FE=1 or ORE=1 or NF=1 in the USARTx_ISR register). + * 0: Interrupt is inhibited + * 1: An interrupt is generated when FE=1 or ORE=1 or NF=1 in the USARTx_ISR register. + * @rmtoll CR3 EIE LL_USART_EnableIT_ERROR + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_ERROR(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_EIE); +} + +/** + * @brief Enable CTS Interrupt + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSIE LL_USART_EnableIT_CTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_CTS(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_CTSIE); +} + +/** + * @brief Enable Wake Up from Stop Mode Interrupt + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUFIE LL_USART_EnableIT_WKUP + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_WKUP(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_WUFIE); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Enable TX FIFO Threshold Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 TXFTIE LL_USART_EnableIT_TXFT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TXFT(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_TXFTIE); +} + +#endif /* USART_CR1_FIFOEN */ +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Enable Smartcard Transmission Complete Before Guard Time Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 TCBGTIE LL_USART_EnableIT_TCBGT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_TCBGT(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_TCBGTIE); +} +#endif /* USART_TCBGT_SUPPORT */ + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Enable RX FIFO Threshold Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 RXFTIE LL_USART_EnableIT_RXFT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableIT_RXFT(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_RXFTIE); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @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); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_DisableIT_RXNE LL_USART_DisableIT_RXNE_RXFNE /* Redefinition for legacy purpose */ + +/** + * @brief Disable RX Not Empty and RX FIFO Not Empty Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 RXNEIE_RXFNEIE LL_USART_DisableIT_RXNE_RXFNE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_RXNE_RXFNE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RXNEIE_RXFNEIE); +} + +#else +/** + * @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); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @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); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_DisableIT_TXE LL_USART_DisableIT_TXE_TXFNF /* Redefinition for legacy purpose */ + +/** + * @brief Disable TX Empty and TX FIFO Not Full Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 TXEIE_TXFNFIE LL_USART_DisableIT_TXE_TXFNF + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TXE_TXFNF(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_TXEIE_TXFNFIE); +} + +#else +/** + * @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); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Disable Parity Error Interrupt + * @rmtoll CR1 PEIE LL_USART_DisableIT_PE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_PE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_PEIE); +} + +/** + * @brief Disable Character Match Interrupt + * @rmtoll CR1 CMIE LL_USART_DisableIT_CM + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_CM(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_CMIE); +} + +/** + * @brief Disable Receiver Timeout Interrupt + * @rmtoll CR1 RTOIE LL_USART_DisableIT_RTO + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_RTO(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RTOIE); +} + +/** + * @brief Disable End Of Block Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR1 EOBIE LL_USART_DisableIT_EOB + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_EOB(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_EOBIE); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Disable TX FIFO Empty Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 TXFEIE LL_USART_DisableIT_TXFE + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TXFE(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_TXFEIE); +} + +/** + * @brief Disable RX FIFO Full Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 RXFFIE LL_USART_DisableIT_RXFF + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_RXFF(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR1, USART_CR1_RXFFIE); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Disable LIN Break Detection Interrupt + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDIE LL_USART_DisableIT_LBD + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_LBD(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR2, USART_CR2_LBDIE); +} + +/** + * @brief Disable Error Interrupt + * @note When set, Error Interrupt Enable Bit is enabling interrupt generation in case of a framing + * error, overrun error or noise flag (FE=1 or ORE=1 or NF=1 in the USARTx_ISR register). + * 0: Interrupt is inhibited + * 1: An interrupt is generated when FE=1 or ORE=1 or NF=1 in the USARTx_ISR register. + * @rmtoll CR3 EIE LL_USART_DisableIT_ERROR + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_ERROR(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_EIE); +} + +/** + * @brief Disable CTS Interrupt + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSIE LL_USART_DisableIT_CTS + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_CTS(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_CTSIE); +} + +/** + * @brief Disable Wake Up from Stop Mode Interrupt + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUFIE LL_USART_DisableIT_WKUP + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_WKUP(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_WUFIE); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Disable TX FIFO Threshold Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 TXFTIE LL_USART_DisableIT_TXFT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TXFT(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_TXFTIE); +} + +#endif /* USART_CR1_FIFOEN */ +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Disable Smartcard Transmission Complete Before Guard Time Interrupt + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 TCBGTIE LL_USART_DisableIT_TCBGT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_TCBGT(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_TCBGTIE); +} +#endif /* USART_TCBGT_SUPPORT */ + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Disable RX FIFO Threshold Interrupt + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 RXFTIE LL_USART_DisableIT_RXFT + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableIT_RXFT(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_RXFTIE); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @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)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_IsEnabledIT_RXNE LL_USART_IsEnabledIT_RXNE_RXFNE /* Redefinition for legacy purpose */ + +/** + * @brief Check if the USART RX Not Empty and USART RX FIFO Not Empty Interrupt is enabled or disabled. + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 RXNEIE_RXFNEIE LL_USART_IsEnabledIT_RXNE_RXFNE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_RXNE_RXFNE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_RXNEIE_RXFNEIE) == (USART_CR1_RXNEIE_RXFNEIE)) ? 1UL : 0UL); +} + +#else +/** + * @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)) ? 1U : 0U); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @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)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +#define LL_USART_IsEnabledIT_TXE LL_USART_IsEnabledIT_TXE_TXFNF /* Redefinition for legacy purpose */ + +/** + * @brief Check if the USART TX Empty and USART TX FIFO Not Full Interrupt is enabled or disabled + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 TXEIE_TXFNFIE LL_USART_IsEnabledIT_TXE_TXFNF + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TXE_TXFNF(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_TXEIE_TXFNFIE) == (USART_CR1_TXEIE_TXFNFIE)) ? 1UL : 0UL); +} + +#else +/** + * @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)) ? 1U : 0U); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @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)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Character Match Interrupt is enabled or disabled. + * @rmtoll CR1 CMIE LL_USART_IsEnabledIT_CM + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_CM(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_CMIE) == (USART_CR1_CMIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Receiver Timeout Interrupt is enabled or disabled. + * @rmtoll CR1 RTOIE LL_USART_IsEnabledIT_RTO + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_RTO(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_RTOIE) == (USART_CR1_RTOIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART End Of Block Interrupt is enabled or disabled. + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR1 EOBIE LL_USART_IsEnabledIT_EOB + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_EOB(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_EOBIE) == (USART_CR1_EOBIE)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Check if the USART TX FIFO Empty Interrupt is enabled or disabled + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 TXFEIE LL_USART_IsEnabledIT_TXFE + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TXFE(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_TXFEIE) == (USART_CR1_TXFEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART RX FIFO Full Interrupt is enabled or disabled + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR1 RXFFIE LL_USART_IsEnabledIT_RXFF + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_RXFF(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR1, USART_CR1_RXFFIE) == (USART_CR1_RXFFIE)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @brief Check if the USART LIN Break Detection Interrupt is enabled or disabled. + * @note Macro IS_UART_LIN_INSTANCE(USARTx) can be used to check whether or not + * LIN feature is supported by the USARTx instance. + * @rmtoll CR2 LBDIE LL_USART_IsEnabledIT_LBD + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_LBD(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR2, USART_CR2_LBDIE) == (USART_CR2_LBDIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Error Interrupt is enabled or disabled. + * @rmtoll CR3 EIE LL_USART_IsEnabledIT_ERROR + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_ERROR(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_EIE) == (USART_CR3_EIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART CTS Interrupt is enabled or disabled. + * @note Macro IS_UART_HWFLOW_INSTANCE(USARTx) can be used to check whether or not + * Hardware Flow control feature is supported by the USARTx instance. + * @rmtoll CR3 CTSIE LL_USART_IsEnabledIT_CTS + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_CTS(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_CTSIE) == (USART_CR3_CTSIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the USART Wake Up from Stop Mode Interrupt is enabled or disabled. + * @note Macro IS_UART_WAKEUP_FROMSTOP_INSTANCE(USARTx) can be used to check whether or not + * Wake-up from Stop mode feature is supported by the USARTx instance. + * @rmtoll CR3 WUFIE LL_USART_IsEnabledIT_WKUP + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_WKUP(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_WUFIE) == (USART_CR3_WUFIE)) ? 1UL : 0UL); +} + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Check if USART TX FIFO Threshold Interrupt is enabled or disabled + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 TXFTIE LL_USART_IsEnabledIT_TXFT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TXFT(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_TXFTIE) == (USART_CR3_TXFTIE)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +#if defined(USART_TCBGT_SUPPORT) +/* Function available only on devices supporting Transmit Complete before Guard Time feature */ +/** + * @brief Check if the Smartcard Transmission Complete Before Guard Time Interrupt is enabled or disabled. + * @note Macro IS_SMARTCARD_INSTANCE(USARTx) can be used to check whether or not + * Smartcard feature is supported by the USARTx instance. + * @rmtoll CR3 TCBGTIE LL_USART_IsEnabledIT_TCBGT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_TCBGT(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_TCBGTIE) == (USART_CR3_TCBGTIE)) ? 1UL : 0UL); +} +#endif /* USART_TCBGT_SUPPORT */ + +#if defined(USART_CR1_FIFOEN) +/** + * @brief Check if USART RX FIFO Threshold Interrupt is enabled or disabled + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @rmtoll CR3 RXFTIE LL_USART_IsEnabledIT_RXFT + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledIT_RXFT(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_RXFTIE) == (USART_CR3_RXFTIE)) ? 1UL : 0UL); +} + +#endif /* USART_CR1_FIFOEN */ +/** + * @} + */ + +/** @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)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Mode for transmission + * @rmtoll CR3 DMAT LL_USART_EnableDMAReq_TX + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDMAReq_TX(USART_TypeDef *USARTx) +{ + ATOMIC_SET_BIT(USARTx->CR3, USART_CR3_DMAT); +} + +/** + * @brief Disable DMA Mode for transmission + * @rmtoll CR3 DMAT LL_USART_DisableDMAReq_TX + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDMAReq_TX(USART_TypeDef *USARTx) +{ + ATOMIC_CLEAR_BIT(USARTx->CR3, USART_CR3_DMAT); +} + +/** + * @brief Check if DMA Mode is enabled for transmission + * @rmtoll CR3 DMAT LL_USART_IsEnabledDMAReq_TX + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDMAReq_TX(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DMAT) == (USART_CR3_DMAT)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Disabling on Reception Error + * @rmtoll CR3 DDRE LL_USART_EnableDMADeactOnRxErr + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_EnableDMADeactOnRxErr(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->CR3, USART_CR3_DDRE); +} + +/** + * @brief Disable DMA Disabling on Reception Error + * @rmtoll CR3 DDRE LL_USART_DisableDMADeactOnRxErr + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_DisableDMADeactOnRxErr(USART_TypeDef *USARTx) +{ + CLEAR_BIT(USARTx->CR3, USART_CR3_DDRE); +} + +/** + * @brief Indicate if DMA Disabling on Reception Error is disabled + * @rmtoll CR3 DDRE LL_USART_IsEnabledDMADeactOnRxErr + * @param USARTx USART Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_USART_IsEnabledDMADeactOnRxErr(const USART_TypeDef *USARTx) +{ + return ((READ_BIT(USARTx->CR3, USART_CR3_DDRE) == (USART_CR3_DDRE)) ? 1UL : 0UL); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll RDR RDR LL_USART_DMA_GetRegAddr\n + * @rmtoll TDR TDR LL_USART_DMA_GetRegAddr + * @param USARTx USART Instance + * @param Direction This parameter can be one of the following values: + * @arg @ref LL_USART_DMA_REG_DATA_TRANSMIT + * @arg @ref LL_USART_DMA_REG_DATA_RECEIVE + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_USART_DMA_GetRegAddr(const USART_TypeDef *USARTx, uint32_t Direction) +{ + uint32_t data_reg_addr; + + if (Direction == LL_USART_DMA_REG_DATA_TRANSMIT) + { + /* return address of TDR register */ + data_reg_addr = (uint32_t) &(USARTx->TDR); + } + else + { + /* return address of RDR register */ + data_reg_addr = (uint32_t) &(USARTx->RDR); + } + + return data_reg_addr; +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Data_Management Data_Management + * @{ + */ + +/** + * @brief Read Receiver Data register (Receive Data value, 8 bits) + * @rmtoll RDR RDR LL_USART_ReceiveData8 + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_USART_ReceiveData8(const USART_TypeDef *USARTx) +{ + return (uint8_t)(READ_BIT(USARTx->RDR, USART_RDR_RDR) & 0xFFU); +} + +/** + * @brief Read Receiver Data register (Receive Data value, 9 bits) + * @rmtoll RDR RDR LL_USART_ReceiveData9 + * @param USARTx USART Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x1FF + */ +__STATIC_INLINE uint16_t LL_USART_ReceiveData9(const USART_TypeDef *USARTx) +{ + return (uint16_t)(READ_BIT(USARTx->RDR, USART_RDR_RDR)); +} + +/** + * @brief Write in Transmitter Data Register (Transmit Data value, 8 bits) + * @rmtoll TDR TDR LL_USART_TransmitData8 + * @param USARTx USART Instance + * @param Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_USART_TransmitData8(USART_TypeDef *USARTx, uint8_t Value) +{ + USARTx->TDR = Value; +} + +/** + * @brief Write in Transmitter Data Register (Transmit Data value, 9 bits) + * @rmtoll TDR TDR LL_USART_TransmitData9 + * @param USARTx USART Instance + * @param Value between Min_Data=0x00 and Max_Data=0x1FF + * @retval None + */ +__STATIC_INLINE void LL_USART_TransmitData9(USART_TypeDef *USARTx, uint16_t Value) +{ + USARTx->TDR = (uint16_t)(Value & 0x1FFUL); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Execution Execution + * @{ + */ + +/** + * @brief Request an Automatic Baud Rate measurement on next received data frame + * @note Macro IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(USARTx) can be used to check whether or not + * Auto Baud Rate detection feature is supported by the USARTx instance. + * @rmtoll RQR ABRRQ LL_USART_RequestAutoBaudRate + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestAutoBaudRate(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_ABRRQ); +} + +/** + * @brief Request Break sending + * @rmtoll RQR SBKRQ LL_USART_RequestBreakSending + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestBreakSending(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_SBKRQ); +} + +/** + * @brief Put USART in mute mode and set the RWU flag + * @rmtoll RQR MMRQ LL_USART_RequestEnterMuteMode + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestEnterMuteMode(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_MMRQ); +} + +/** + @if USART_CR1_FIFOEN + * @brief Request a Receive Data and FIFO flush + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + * @note Allows to discard the received data without reading them, and avoid an overrun + * condition. + @else + * @brief Request a Receive Data flush + @endif + * @rmtoll RQR RXFRQ LL_USART_RequestRxDataFlush + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestRxDataFlush(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_RXFRQ); +} + +/** + @if USART_CR1_FIFOEN + * @brief Request a Transmit data and FIFO flush + * @note Macro IS_UART_FIFO_INSTANCE(USARTx) can be used to check whether or not + * FIFO mode feature is supported by the USARTx instance. + @else + * @brief Request a Transmit data flush + @endif + * @rmtoll RQR TXFRQ LL_USART_RequestTxDataFlush + * @param USARTx USART Instance + * @retval None + */ +__STATIC_INLINE void LL_USART_RequestTxDataFlush(USART_TypeDef *USARTx) +{ + SET_BIT(USARTx->RQR, (uint16_t)USART_RQR_TXFRQ); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_EF_Init Initialization and de-initialization functions + * @{ + */ +ErrorStatus LL_USART_DeInit(const USART_TypeDef *USARTx); +ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, const LL_USART_InitTypeDef *USART_InitStruct); +void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct); +ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, const LL_USART_ClockInitTypeDef *USART_ClockInitStruct); +void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct); +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* USART1 || USART2 || USART3 || UART4 || UART5 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_USART_H */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_utils.h b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_utils.h new file mode 100644 index 0000000..d465c0d --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Inc/stm32l4xx_ll_utils.h @@ -0,0 +1,329 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_utils.h + * @author MCD Application Team + * @brief Header file of UTILS 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. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The LL UTILS driver contains a set of generic APIs that can be + used by user: + (+) Device electronic signature + (+) Timing functions + (+) PLL configuration functions + + @endverbatim + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32L4xx_LL_UTILS_H +#define STM32L4xx_LL_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +/** @defgroup UTILS_LL UTILS + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup UTILS_LL_Private_Constants UTILS Private Constants + * @{ + */ + +/* Max delay can be used in LL_mDelay */ +#define LL_MAX_DELAY 0xFFFFFFFFU + +/** + * @brief Unique device ID register base address + */ +#define UID_BASE_ADDRESS UID_BASE + +/** + * @brief Flash size data register base address + */ +#define FLASHSIZE_BASE_ADDRESS FLASHSIZE_BASE + +/** + * @brief Package data register base address + */ +#define PACKAGE_BASE_ADDRESS PACKAGE_BASE + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup UTILS_LL_Private_Macros UTILS Private Macros + * @{ + */ +/** + * @} + */ +/* Exported types ------------------------------------------------------------*/ +/** @defgroup UTILS_LL_ES_INIT UTILS Exported structures + * @{ + */ +/** + * @brief UTILS PLL structure definition + */ +typedef struct +{ + uint32_t PLLM; /*!< Division factor for PLL VCO input clock. + This parameter can be a value of @ref RCC_LL_EC_PLLM_DIV + + This feature can be modified afterwards using unitary function + @ref LL_RCC_PLL_ConfigDomain_SYS(). */ + + uint32_t PLLN; /*!< Multiplication factor for PLL VCO output clock. + This parameter must be a number between Min_Data = 8 and Max_Data = 86 + + This feature can be modified afterwards using unitary function + @ref LL_RCC_PLL_ConfigDomain_SYS(). */ + + uint32_t PLLR; /*!< Division for the main system clock. + This parameter can be a value of @ref RCC_LL_EC_PLLR_DIV + + This feature can be modified afterwards using unitary function + @ref LL_RCC_PLL_ConfigDomain_SYS(). */ +} LL_UTILS_PLLInitTypeDef; + +/** + * @brief UTILS System, AHB and APB buses clock configuration structure definition + */ +typedef struct +{ + uint32_t AHBCLKDivider; /*!< The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK). + This parameter can be a value of @ref RCC_LL_EC_SYSCLK_DIV + + This feature can be modified afterwards using unitary function + @ref LL_RCC_SetAHBPrescaler(). */ + + uint32_t APB1CLKDivider; /*!< The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK). + This parameter can be a value of @ref RCC_LL_EC_APB1_DIV + + This feature can be modified afterwards using unitary function + @ref LL_RCC_SetAPB1Prescaler(). */ + + uint32_t APB2CLKDivider; /*!< The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK). + This parameter can be a value of @ref RCC_LL_EC_APB2_DIV + + This feature can be modified afterwards using unitary function + @ref LL_RCC_SetAPB2Prescaler(). */ + +} LL_UTILS_ClkInitTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup UTILS_LL_Exported_Constants UTILS Exported Constants + * @{ + */ + +/** @defgroup UTILS_EC_HSE_BYPASS HSE Bypass activation + * @{ + */ +#define LL_UTILS_HSEBYPASS_OFF 0x00000000U /*!< HSE Bypass is not enabled */ +#define LL_UTILS_HSEBYPASS_ON 0x00000001U /*!< HSE Bypass is enabled */ +/** + * @} + */ + +/** @defgroup UTILS_EC_PACKAGETYPE PACKAGE TYPE + * @{ + */ +#define LL_UTILS_PACKAGETYPE_LQFP64 0x00000000U /*!< LQFP64 package type */ +#define LL_UTILS_PACKAGETYPE_WLCSP64 0x00000001U /*!< WLCSP64 package type */ +#define LL_UTILS_PACKAGETYPE_LQFP100 0x00000002U /*!< LQFP100 package type */ +#define LL_UTILS_PACKAGETYPE_BGA132 0x00000003U /*!< BGA132 package type */ +#define LL_UTILS_PACKAGETYPE_LQFP144_CSP72 0x00000004U /*!< LQFP144, WLCSP81 or WLCSP72 package type */ +#define LL_UTILS_PACKAGETYPE_UFQFPN32 0x00000008U /*!< UFQFPN32 package type */ +#define LL_UTILS_PACKAGETYPE_UFQFPN48 0x0000000AU /*!< UFQFPN48 package type */ +#define LL_UTILS_PACKAGETYPE_LQFP48 0x0000000BU /*!< LQFP48 package type */ +#define LL_UTILS_PACKAGETYPE_WLCSP49 0x0000000CU /*!< WLCSP49 package type */ +#define LL_UTILS_PACKAGETYPE_UFBGA64 0x0000000DU /*!< UFBGA64 package type */ +#define LL_UTILS_PACKAGETYPE_UFBGA100 0x0000000EU /*!< UFBGA100 package type */ +#define LL_UTILS_PACKAGETYPE_UFBGA169_CSP115 0x00000010U /*!< UFBGA169 or WLCSP115 package type */ +#define LL_UTILS_PACKAGETYPE_LQFP100_DSI 0x00000012U /*!< LQFP100 with DSI package type */ +#define LL_UTILS_PACKAGETYPE_WLCSP144_DSI 0x00000013U /*!< WLCSP144 with DSI package type */ +#define LL_UTILS_PACKAGETYPE_UFBGA144_DSI 0x00000013U /*!< UFBGA144 with DSI package type */ +#define LL_UTILS_PACKAGETYPE_UFBGA169_DSI 0x00000014U /*!< UFBGA169 with DSI package type */ +#define LL_UTILS_PACKAGETYPE_LQFP144_DSI 0x00000015U /*!< LQFP144 with DSI package type */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup UTILS_LL_Exported_Functions UTILS Exported Functions + * @{ + */ + +/** @defgroup UTILS_EF_DEVICE_ELECTRONIC_SIGNATURE DEVICE ELECTRONIC SIGNATURE + * @{ + */ + +/** + * @brief Get Word0 of the unique device identifier (UID based on 96 bits) + * @retval UID[31:0]: X and Y coordinates on the wafer expressed in BCD format + */ +__STATIC_INLINE uint32_t LL_GetUID_Word0(void) +{ + return (uint32_t)(READ_REG(*((uint32_t *)UID_BASE_ADDRESS))); +} + +/** + * @brief Get Word1 of the unique device identifier (UID based on 96 bits) + * @retval UID[63:32]: Wafer number (UID[39:32]) & LOT_NUM[23:0] (UID[63:40]) + */ +__STATIC_INLINE uint32_t LL_GetUID_Word1(void) +{ + return (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE_ADDRESS + 4U)))); +} + +/** + * @brief Get Word2 of the unique device identifier (UID based on 96 bits) + * @retval UID[95:64]: Lot number (ASCII encoded) - LOT_NUM[55:24] + */ +__STATIC_INLINE uint32_t LL_GetUID_Word2(void) +{ + return (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE_ADDRESS + 8U)))); +} + +/** + * @brief Get Flash memory size + * @note This bitfield indicates the size of the device Flash memory expressed in + * Kbytes. As an example, 0x040 corresponds to 64 Kbytes. + * @retval FLASH_SIZE[15:0]: Flash memory size + */ +__STATIC_INLINE uint32_t LL_GetFlashSize(void) +{ + return (uint32_t)(READ_REG(*((uint32_t *)FLASHSIZE_BASE_ADDRESS)) & 0xFFFFU); +} + +/** + * @brief Get Package type + * @retval Returned value can be one of the following values: + * @arg @ref LL_UTILS_PACKAGETYPE_LQFP64 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_LQFP100 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_BGA132 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_LQFP144_CSP72 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFQFPN32 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFQFPN48 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_LQFP48 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_WLCSP49 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFBGA64 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFBGA100 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFBGA169 (*) + * @arg @ref LL_UTILS_PACKAGETYPE_LQFP100_DSI (*) + * @arg @ref LL_UTILS_PACKAGETYPE_WLCSP144_DSI (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFBGA144_DSI (*) + * @arg @ref LL_UTILS_PACKAGETYPE_UFBGA169_DSI (*) + * @arg @ref LL_UTILS_PACKAGETYPE_LQFP144_DSI (*) + * + * (*) value not defined in all devices. + */ +__STATIC_INLINE uint32_t LL_GetPackageType(void) +{ + return (uint32_t)(READ_REG(*((uint32_t *)PACKAGE_BASE_ADDRESS)) & 0x1FU); +} + +/** + * @} + */ + +/** @defgroup UTILS_LL_EF_DELAY DELAY + * @{ + */ + +/** + * @brief This function configures the Cortex-M SysTick source of the time base. + * @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro) + * @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 Ticks Number of ticks + * @retval None + */ +__STATIC_INLINE void LL_InitTick(uint32_t HCLKFrequency, uint32_t Ticks) +{ + /* Configure the SysTick to have interrupt in 1ms time base */ + SysTick->LOAD = (uint32_t)((HCLKFrequency / Ticks) - 1UL); /* set reload register */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable the Systick Timer */ +} + +void LL_Init1msTick(uint32_t HCLKFrequency); +void LL_mDelay(uint32_t Delay); + +/** + * @} + */ + +/** @defgroup UTILS_EF_SYSTEM SYSTEM + * @{ + */ + +void LL_SetSystemCoreClock(uint32_t HCLKFrequency); +ErrorStatus LL_SetFlashLatency(uint32_t HCLKFrequency); +ErrorStatus LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, + LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct); +ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, + LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct); +ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass, + LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32L4xx_LL_UTILS_H */ diff --git a/Drivers/STM32L4xx_HAL_Driver/LICENSE.txt b/Drivers/STM32L4xx_HAL_Driver/LICENSE.txt new file mode 100644 index 0000000..3edc4d1 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/LICENSE.txt @@ -0,0 +1,6 @@ +This software component is provided to you as part of a software package and +applicable license terms are in the Package_license file. If you received this +software component outside of a package or without applicable license terms, +the terms of the BSD-3-Clause license shall apply. +You may obtain a copy of the BSD-3-Clause at: +https://opensource.org/licenses/BSD-3-Clause diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_adc.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_adc.c new file mode 100644 index 0000000..8fde353 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_adc.c @@ -0,0 +1,1062 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 "stm32l4xx_ll_adc.h" +#include "stm32l4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (ADC1) || defined (ADC2) || defined (ADC3) + +/** @addtogroup ADC_LL ADC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup ADC_LL_Private_Constants + * @{ + */ + +/* Definitions of ADC hardware constraints delays */ +/* Note: Only ADC peripheral 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. */ +/* Refer to @ref ADC_LL_EC_HW_DELAYS for description of ADC timeout */ +/* values definition. */ +/* Note: ADC timeout values are defined here in CPU cycles to be independent */ +/* of device clock setting. */ +/* In user application, ADC timeout values should be defined with */ +/* temporal values, in function of device clock settings. */ +/* Highest ratio CPU clock frequency vs ADC clock frequency: */ +/* - ADC clock from synchronous clock with AHB prescaler 512, */ +/* APB prescaler 16, ADC prescaler 4. */ +/* - ADC clock from asynchronous clock (PLLSAI) with prescaler 1, */ +/* with highest ratio CPU clock frequency vs HSI clock frequency: */ +/* CPU clock frequency max 72MHz, PLLSAI freq min 26MHz: ratio 4. */ +/* Unit: CPU cycles. */ +#define ADC_CLOCK_RATIO_VS_CPU_HIGHEST (512UL * 16UL * 4UL) +#define ADC_TIMEOUT_DISABLE_CPU_CYCLES (ADC_CLOCK_RATIO_VS_CPU_HIGHEST * 1UL) +#define ADC_TIMEOUT_STOP_CONVERSION_CPU_CYCLES (ADC_CLOCK_RATIO_VS_CPU_HIGHEST * 1UL) + +/** + * @} + */ + +/* 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_DIV1) \ + || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV2) \ + || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV4) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV1) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV2) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV4) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV6) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV8) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV10) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV12) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV16) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV32) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV64) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV128) \ + || ((__CLOCK__) == LL_ADC_CLOCK_ASYNC_DIV256) \ + ) + +/* 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_LOW_POWER(__LOW_POWER__) \ + (((__LOW_POWER__) == LL_ADC_LP_MODE_NONE) \ + || ((__LOW_POWER__) == LL_ADC_LP_AUTOWAIT) \ + ) + +/* 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_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_TRGO2) \ + || ((__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_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_CH4) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM6_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO2) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM15_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_OVR_DATA_BEHAVIOR(__REG_OVR_DATA_BEHAVIOR__) \ + (((__REG_OVR_DATA_BEHAVIOR__) == LL_ADC_REG_OVR_DATA_PRESERVED) \ + || ((__REG_OVR_DATA_BEHAVIOR__) == LL_ADC_REG_OVR_DATA_OVERWRITTEN) \ + ) + +#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_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO2) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH1) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH3) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM6_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_TRGO2) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM15_TRGO) \ + || ((__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. */ +#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) \ + ) + +#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_RES12_10B) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_LIMIT_RES8_6B) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_UNLMT_RES12_10B) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_UNLMT_RES8_6B) \ + ) + +#define IS_LL_ADC_MULTI_TWOSMP_DELAY(__MULTI_TWOSMP_DELAY__) \ + (((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_2CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_3CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_4CYCLES) \ + || ((__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) \ + ) + +#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. + * @note This function is performing a hard reset, using high level + * clock source RCC ADC reset. + * Caution: On this STM32 series, if several ADC instances are available + * on the selected device, RCC ADC reset will reset + * all ADC instances belonging to the common ADC instance. + * To de-initialize only 1 ADC instance, use + * function @ref LL_ADC_DeInit(). + * @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(const ADC_Common_TypeDef *ADCxy_COMMON) +{ + /* Check the parameters */ + assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON)); + + /* Prevent unused argument compilation warning */ + (void)(ADCxy_COMMON); + + /* Force reset of ADC clock (core clock) */ + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_ADC); + + /* Release reset of ADC clock (core clock) */ + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_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 pADC_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, const LL_ADC_CommonInitTypeDef *pADC_CommonInitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON)); + assert_param(IS_LL_ADC_COMMON_CLOCK(pADC_CommonInitStruct->CommonClock)); + +#if defined(ADC_MULTIMODE_SUPPORT) + assert_param(IS_LL_ADC_MULTI_MODE(pADC_CommonInitStruct->Multimode)); + if (pADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT) + { + assert_param(IS_LL_ADC_MULTI_DMA_TRANSFER(pADC_CommonInitStruct->MultiDMATransfer)); + assert_param(IS_LL_ADC_MULTI_TWOSMP_DELAY(pADC_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 (pADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT) + { + MODIFY_REG(ADCxy_COMMON->CCR, + ADC_CCR_CKMODE + | ADC_CCR_PRESC + | ADC_CCR_DUAL + | ADC_CCR_MDMA + | ADC_CCR_DELAY + , + pADC_CommonInitStruct->CommonClock + | pADC_CommonInitStruct->Multimode + | pADC_CommonInitStruct->MultiDMATransfer + | pADC_CommonInitStruct->MultiTwoSamplingDelay + ); + } + else + { + MODIFY_REG(ADCxy_COMMON->CCR, + ADC_CCR_CKMODE + | ADC_CCR_PRESC + | ADC_CCR_DUAL + | ADC_CCR_MDMA + | ADC_CCR_DELAY + , + pADC_CommonInitStruct->CommonClock + | LL_ADC_MULTI_INDEPENDENT + ); + } +#else + LL_ADC_SetCommonClock(ADCxy_COMMON, pADC_CommonInitStruct->CommonClock); +#endif /* ADC_MULTIMODE_SUPPORT */ + } + 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 pADC_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 *pADC_CommonInitStruct) +{ + /* Set pADC_CommonInitStruct fields to default values */ + /* Set fields of ADC common */ + /* (all ADC instances belonging to the same ADC common instance) */ + pADC_CommonInitStruct->CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV2; + +#if defined(ADC_MULTIMODE_SUPPORT) + /* Set fields of ADC multimode */ + pADC_CommonInitStruct->Multimode = LL_ADC_MULTI_INDEPENDENT; + pADC_CommonInitStruct->MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC; + pADC_CommonInitStruct->MultiTwoSamplingDelay = LL_ADC_MULTI_TWOSMP_DELAY_1CYCLE; +#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(). + * @note If this functions returns error status, it means that ADC instance + * is in an unknown state. + * In this case, perform a hard reset using high level + * clock source RCC ADC reset. + * Caution: On this STM32 series, if several ADC instances are available + * on the selected device, RCC ADC reset will reset + * all ADC instances belonging to the common ADC instance. + * Refer to 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; + + __IO uint32_t timeout_cpu_cycles = 0UL; + + /* 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); + + /* Stop potential ADC conversion on going on ADC group regular. */ + if (LL_ADC_REG_IsConversionOngoing(ADCx) != 0UL) + { + if (LL_ADC_REG_IsStopConversionOngoing(ADCx) == 0UL) + { + LL_ADC_REG_StopConversion(ADCx); + } + } + + /* 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); + + /* Stop potential ADC conversion on going on ADC group injected. */ + if (LL_ADC_INJ_IsConversionOngoing(ADCx) != 0UL) + { + if (LL_ADC_INJ_IsStopConversionOngoing(ADCx) == 0UL) + { + LL_ADC_INJ_StopConversion(ADCx); + } + } + + /* Wait for ADC conversions are effectively stopped */ + timeout_cpu_cycles = ADC_TIMEOUT_STOP_CONVERSION_CPU_CYCLES; + while ((LL_ADC_REG_IsStopConversionOngoing(ADCx) + | LL_ADC_INJ_IsStopConversionOngoing(ADCx)) == 1UL) + { + timeout_cpu_cycles--; + if (timeout_cpu_cycles == 0UL) + { + /* Time-out error */ + status = ERROR; + break; + } + } + + /* Flush group injected contexts queue (register JSQR): */ + /* Note: Bit JQM must be set to empty the contexts queue (otherwise */ + /* contexts queue is maintained with the last active context). */ + LL_ADC_INJ_SetQueueMode(ADCx, LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY); + + /* Disable the ADC instance */ + LL_ADC_Disable(ADCx); + + /* Wait for ADC instance is effectively disabled */ + timeout_cpu_cycles = ADC_TIMEOUT_DISABLE_CPU_CYCLES; + while (LL_ADC_IsDisableOngoing(ADCx) == 1UL) + { + timeout_cpu_cycles--; + if (timeout_cpu_cycles == 0UL) + { + /* Time-out error */ + status = ERROR; + break; + } + } + } + + /* Check whether ADC state is compliant with expected state */ + if (READ_BIT(ADCx->CR, + (ADC_CR_JADSTP | ADC_CR_ADSTP | ADC_CR_JADSTART | ADC_CR_ADSTART + | ADC_CR_ADDIS | ADC_CR_ADEN) + ) + == 0UL) + { + /* ========== Reset ADC registers ========== */ + /* Reset register IER */ + CLEAR_BIT(ADCx->IER, + (LL_ADC_IT_ADRDY + | LL_ADC_IT_EOC + | LL_ADC_IT_EOS + | LL_ADC_IT_OVR + | LL_ADC_IT_EOSMP + | LL_ADC_IT_JEOC + | LL_ADC_IT_JEOS + | LL_ADC_IT_JQOVF + | LL_ADC_IT_AWD1 + | LL_ADC_IT_AWD2 + | LL_ADC_IT_AWD3 + ) + ); + + /* Reset register ISR */ + SET_BIT(ADCx->ISR, + (LL_ADC_FLAG_ADRDY + | LL_ADC_FLAG_EOC + | LL_ADC_FLAG_EOS + | LL_ADC_FLAG_OVR + | LL_ADC_FLAG_EOSMP + | LL_ADC_FLAG_JEOC + | LL_ADC_FLAG_JEOS + | LL_ADC_FLAG_JQOVF + | LL_ADC_FLAG_AWD1 + | LL_ADC_FLAG_AWD2 + | LL_ADC_FLAG_AWD3 + ) + ); + + /* Reset register CR */ + /* - Bits ADC_CR_JADSTP, ADC_CR_ADSTP, ADC_CR_JADSTART, ADC_CR_ADSTART, */ + /* ADC_CR_ADCAL, ADC_CR_ADDIS, ADC_CR_ADEN are in */ + /* access mode "read-set": no direct reset applicable. */ + /* - Reset Calibration mode to default setting (single ended). */ + /* - Disable ADC internal voltage regulator. */ + /* - Enable ADC deep power down. */ + /* Note: ADC internal voltage regulator disable and ADC deep power */ + /* down enable are conditioned to ADC state disabled: */ + /* already done above. */ + CLEAR_BIT(ADCx->CR, ADC_CR_ADVREGEN | ADC_CR_ADCALDIF); + SET_BIT(ADCx->CR, ADC_CR_DEEPPWD); + + /* Reset register CFGR */ + MODIFY_REG(ADCx->CFGR, + (ADC_CFGR_AWD1CH | ADC_CFGR_JAUTO | ADC_CFGR_JAWD1EN + | ADC_CFGR_AWD1EN | ADC_CFGR_AWD1SGL | ADC_CFGR_JQM + | ADC_CFGR_JDISCEN | ADC_CFGR_DISCNUM | ADC_CFGR_DISCEN + | ADC_CFGR_AUTDLY | ADC_CFGR_CONT | ADC_CFGR_OVRMOD + | ADC_CFGR_EXTEN | ADC_CFGR_EXTSEL | ADC_CFGR_ALIGN + | ADC_CFGR_RES | ADC_CFGR_DMACFG | ADC_CFGR_DMAEN), + ADC_CFGR_JQDIS + ); + + /* Reset register CFGR2 */ + CLEAR_BIT(ADCx->CFGR2, + (ADC_CFGR2_ROVSM | ADC_CFGR2_TROVS | ADC_CFGR2_OVSS + | ADC_CFGR2_OVSR | ADC_CFGR2_JOVSE | ADC_CFGR2_ROVSE) + ); + + /* Reset register SMPR1 */ + CLEAR_BIT(ADCx->SMPR1, + (ADC_SMPR1_SMP9 | ADC_SMPR1_SMP8 | ADC_SMPR1_SMP7 + | ADC_SMPR1_SMP6 | ADC_SMPR1_SMP5 | ADC_SMPR1_SMP4 + | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP1) + ); + + /* Reset register SMPR2 */ + CLEAR_BIT(ADCx->SMPR2, + (ADC_SMPR2_SMP18 | ADC_SMPR2_SMP17 | ADC_SMPR2_SMP16 + | ADC_SMPR2_SMP15 | ADC_SMPR2_SMP14 | ADC_SMPR2_SMP13 + | ADC_SMPR2_SMP12 | ADC_SMPR2_SMP11 | ADC_SMPR2_SMP10) + ); + + /* Reset register TR1 */ + MODIFY_REG(ADCx->TR1, ADC_TR1_HT1 | ADC_TR1_LT1, ADC_TR1_HT1); + + /* Reset register TR2 */ + MODIFY_REG(ADCx->TR2, ADC_TR2_HT2 | ADC_TR2_LT2, ADC_TR2_HT2); + + /* Reset register TR3 */ + MODIFY_REG(ADCx->TR3, ADC_TR3_HT3 | ADC_TR3_LT3, ADC_TR3_HT3); + + /* Reset register SQR1 */ + CLEAR_BIT(ADCx->SQR1, + (ADC_SQR1_SQ4 | ADC_SQR1_SQ3 | ADC_SQR1_SQ2 + | ADC_SQR1_SQ1 | ADC_SQR1_L) + ); + + /* Reset register SQR2 */ + CLEAR_BIT(ADCx->SQR2, + (ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7 + | ADC_SQR2_SQ6 | ADC_SQR2_SQ5) + ); + + /* Reset register SQR3 */ + CLEAR_BIT(ADCx->SQR3, + (ADC_SQR3_SQ14 | ADC_SQR3_SQ13 | ADC_SQR3_SQ12 + | ADC_SQR3_SQ11 | ADC_SQR3_SQ10) + ); + + /* Reset register SQR4 */ + CLEAR_BIT(ADCx->SQR4, ADC_SQR4_SQ16 | ADC_SQR4_SQ15); + + /* Reset register JSQR */ + CLEAR_BIT(ADCx->JSQR, + (ADC_JSQR_JL + | ADC_JSQR_JEXTSEL | ADC_JSQR_JEXTEN + | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 + | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1) + ); + + /* Reset register DR */ + /* Note: bits in access mode read only, no direct reset applicable */ + + /* Reset register OFR1 */ + CLEAR_BIT(ADCx->OFR1, ADC_OFR1_OFFSET1_EN | ADC_OFR1_OFFSET1_CH | ADC_OFR1_OFFSET1); + /* Reset register OFR2 */ + CLEAR_BIT(ADCx->OFR2, ADC_OFR2_OFFSET2_EN | ADC_OFR2_OFFSET2_CH | ADC_OFR2_OFFSET2); + /* Reset register OFR3 */ + CLEAR_BIT(ADCx->OFR3, ADC_OFR3_OFFSET3_EN | ADC_OFR3_OFFSET3_CH | ADC_OFR3_OFFSET3); + /* Reset register OFR4 */ + CLEAR_BIT(ADCx->OFR4, ADC_OFR4_OFFSET4_EN | ADC_OFR4_OFFSET4_CH | ADC_OFR4_OFFSET4); + + /* Reset registers JDR1, JDR2, JDR3, JDR4 */ + /* Note: bits in access mode read only, no direct reset applicable */ + + /* Reset register AWD2CR */ + CLEAR_BIT(ADCx->AWD2CR, ADC_AWD2CR_AWD2CH); + + /* Reset register AWD3CR */ + CLEAR_BIT(ADCx->AWD3CR, ADC_AWD3CR_AWD3CH); + + /* Reset register DIFSEL */ + CLEAR_BIT(ADCx->DIFSEL, ADC_DIFSEL_DIFSEL); + + /* Reset register CALFACT */ + CLEAR_BIT(ADCx->CALFACT, ADC_CALFACT_CALFACT_D | ADC_CALFACT_CALFACT_S); + } + else + { + /* ADC instance is in an unknown state */ + /* Need to performing a hard reset of ADC instance, using high level */ + /* clock source RCC ADC reset. */ + /* Caution: On this STM32 series, if several ADC instances are available */ + /* on the selected device, RCC ADC reset will reset */ + /* all ADC instances belonging to the common ADC instance. */ + /* Caution: On this STM32 series, if several ADC instances are available */ + /* on the selected device, RCC ADC reset will reset */ + /* all ADC instances belonging to the common ADC instance. */ + status = ERROR; + } + + 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 series). + * 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 series. 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 pADC_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, const LL_ADC_InitTypeDef *pADC_InitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + + assert_param(IS_LL_ADC_RESOLUTION(pADC_InitStruct->Resolution)); + assert_param(IS_LL_ADC_DATA_ALIGN(pADC_InitStruct->DataAlignment)); + assert_param(IS_LL_ADC_LOW_POWER(pADC_InitStruct->LowPowerMode)); + + /* 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 */ + /* - Set ADC low power mode */ + MODIFY_REG(ADCx->CFGR, + ADC_CFGR_RES + | ADC_CFGR_ALIGN + | ADC_CFGR_AUTDLY + , + pADC_InitStruct->Resolution + | pADC_InitStruct->DataAlignment + | pADC_InitStruct->LowPowerMode + ); + + } + else + { + /* Initialization error: ADC instance is not disabled. */ + status = ERROR; + } + + return status; +} + +/** + * @brief Set each @ref LL_ADC_InitTypeDef field to default value. + * @param pADC_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 *pADC_InitStruct) +{ + /* Set pADC_InitStruct fields to default values */ + /* Set fields of ADC instance */ + pADC_InitStruct->Resolution = LL_ADC_RESOLUTION_12B; + pADC_InitStruct->DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; + pADC_InitStruct->LowPowerMode = LL_ADC_LP_MODE_NONE; + +} + +/** + * @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 series. 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 pADC_RegInitStruct 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, const LL_ADC_REG_InitTypeDef *pADC_RegInitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + assert_param(IS_LL_ADC_REG_TRIG_SOURCE(pADC_RegInitStruct->TriggerSource)); + assert_param(IS_LL_ADC_REG_SEQ_SCAN_LENGTH(pADC_RegInitStruct->SequencerLength)); + if (pADC_RegInitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) + { + assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(pADC_RegInitStruct->SequencerDiscont)); + + /* ADC group regular continuous mode and discontinuous mode */ + /* can not be enabled simultenaeously */ + assert_param((pADC_RegInitStruct->ContinuousMode == LL_ADC_REG_CONV_SINGLE) + || (pADC_RegInitStruct->SequencerDiscont == LL_ADC_REG_SEQ_DISCONT_DISABLE)); + } + assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(pADC_RegInitStruct->ContinuousMode)); + assert_param(IS_LL_ADC_REG_DMA_TRANSFER(pADC_RegInitStruct->DMATransfer)); + assert_param(IS_LL_ADC_REG_OVR_DATA_BEHAVIOR(pADC_RegInitStruct->Overrun)); + + /* 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 */ + /* - Set ADC group regular overrun behavior */ + /* Note: On this STM32 series, ADC trigger edge is set to value 0x0 by */ + /* setting of trigger source to SW start. */ + if (pADC_RegInitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) + { + MODIFY_REG(ADCx->CFGR, + ADC_CFGR_EXTSEL + | ADC_CFGR_EXTEN + | ADC_CFGR_DISCEN + | ADC_CFGR_DISCNUM + | ADC_CFGR_CONT + | ADC_CFGR_DMAEN + | ADC_CFGR_DMACFG + | ADC_CFGR_OVRMOD + , + pADC_RegInitStruct->TriggerSource + | pADC_RegInitStruct->SequencerDiscont + | pADC_RegInitStruct->ContinuousMode + | pADC_RegInitStruct->DMATransfer + | pADC_RegInitStruct->Overrun + ); + } + else + { + MODIFY_REG(ADCx->CFGR, + ADC_CFGR_EXTSEL + | ADC_CFGR_EXTEN + | ADC_CFGR_DISCEN + | ADC_CFGR_DISCNUM + | ADC_CFGR_CONT + | ADC_CFGR_DMAEN + | ADC_CFGR_DMACFG + | ADC_CFGR_OVRMOD + , + pADC_RegInitStruct->TriggerSource + | LL_ADC_REG_SEQ_DISCONT_DISABLE + | pADC_RegInitStruct->ContinuousMode + | pADC_RegInitStruct->DMATransfer + | pADC_RegInitStruct->Overrun + ); + } + + /* Set ADC group regular sequencer length and scan direction */ + LL_ADC_REG_SetSequencerLength(ADCx, pADC_RegInitStruct->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 pADC_RegInitStruct 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 *pADC_RegInitStruct) +{ + /* Set pADC_RegInitStruct fields to default values */ + /* Set fields of ADC group regular */ + /* Note: On this STM32 series, ADC trigger edge is set to value 0x0 by */ + /* setting of trigger source to SW start. */ + pADC_RegInitStruct->TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; + pADC_RegInitStruct->SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE; + pADC_RegInitStruct->SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; + pADC_RegInitStruct->ContinuousMode = LL_ADC_REG_CONV_SINGLE; + pADC_RegInitStruct->DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE; + pADC_RegInitStruct->Overrun = LL_ADC_REG_OVR_DATA_OVERWRITTEN; +} + +/** + * @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 series. 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(); + * @note Caution if feature ADC group injected contexts queue is enabled + * (refer to with function @ref LL_ADC_INJ_SetQueueMode() ): + * using successively several times this function will appear as + * having no effect. + * To set several features of ADC group injected, use + * function @ref LL_ADC_INJ_ConfigQueueContext(). + * @param ADCx ADC instance + * @param pADC_InjInitStruct 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, const LL_ADC_INJ_InitTypeDef *pADC_InjInitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(pADC_InjInitStruct->TriggerSource)); + assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(pADC_InjInitStruct->SequencerLength)); + if (pADC_InjInitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE) + { + assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(pADC_InjInitStruct->SequencerDiscont)); + } + assert_param(IS_LL_ADC_INJ_TRIG_AUTO(pADC_InjInitStruct->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 to value 0x0 by */ + /* setting of trigger source to SW start. */ + if (pADC_InjInitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) + { + MODIFY_REG(ADCx->CFGR, + ADC_CFGR_JDISCEN + | ADC_CFGR_JAUTO + , + pADC_InjInitStruct->SequencerDiscont + | pADC_InjInitStruct->TrigAuto + ); + } + else + { + MODIFY_REG(ADCx->CFGR, + ADC_CFGR_JDISCEN + | ADC_CFGR_JAUTO + , + LL_ADC_REG_SEQ_DISCONT_DISABLE + | pADC_InjInitStruct->TrigAuto + ); + } + + MODIFY_REG(ADCx->JSQR, + ADC_JSQR_JEXTSEL + | ADC_JSQR_JEXTEN + | ADC_JSQR_JL + , + pADC_InjInitStruct->TriggerSource + | pADC_InjInitStruct->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 pADC_InjInitStruct 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 *pADC_InjInitStruct) +{ + /* Set pADC_InjInitStruct fields to default values */ + /* Set fields of ADC group injected */ + pADC_InjInitStruct->TriggerSource = LL_ADC_INJ_TRIG_SOFTWARE; + pADC_InjInitStruct->SequencerLength = LL_ADC_INJ_SEQ_SCAN_DISABLE; + pADC_InjInitStruct->SequencerDiscont = LL_ADC_INJ_SEQ_DISCONT_DISABLE; + pADC_InjInitStruct->TrigAuto = LL_ADC_INJ_TRIG_INDEPENDENT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ADC1 || ADC2 || ADC3 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dac.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dac.c new file mode 100644 index 0000000..cebf762 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dac.c @@ -0,0 +1,323 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_dac.c + * @author MCD Application Team + * @brief DAC 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 "stm32l4xx_ll_dac.h" +#include "stm32l4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT + #include "stm32_assert.h" +#else + #define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (DAC1) + +/** @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(__DAC_CHANNEL__) \ + ( \ + ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \ + || ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_2) \ + ) +#else +#define IS_LL_DAC_CHANNEL(__DAC_CHANNEL__) \ + ( \ + ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \ + ) +#endif /* DAC_CHANNEL2_SUPPORT */ + +#if defined (DAC_CR_TSEL1_3) +#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \ + ( ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM1_TRGO) \ + || ((__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_TIM15_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM1_OUT) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_LPTIM2_OUT) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \ + ) +#else +#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) \ + ) +#endif /* DAC_CR_TSEL1_3 */ + +#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) \ + ) + +#define IS_LL_DAC_OUTPUT_CONNECTION(__OUTPUT_CONNECTION__) \ + ( ((__OUTPUT_CONNECTION__) == LL_DAC_OUTPUT_CONNECT_GPIO) \ + || ((__OUTPUT_CONNECTION__) == LL_DAC_OUTPUT_CONNECT_INTERNAL) \ + ) + +#define IS_LL_DAC_OUTPUT_MODE(__OUTPUT_MODE__) \ + ( ((__OUTPUT_MODE__) == LL_DAC_OUTPUT_MODE_NORMAL) \ + || ((__OUTPUT_MODE__) == LL_DAC_OUTPUT_MODE_SAMPLE_AND_HOLD) \ + ) + +/** + * @} + */ + + +/* 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) +{ + + /* Prevent unused argument(s) compilation warning */ + (void)(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 series, 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(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_OUTPUT_CONNECTION(DAC_InitStruct->OutputConnection)); + assert_param(IS_LL_DAC_OUTPUT_MODE(DAC_InitStruct->OutputMode)); + 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) == 0U) + { + /* Configuration of DAC channel: */ + /* - TriggerSource */ + /* - WaveAutoGeneration */ + /* - OutputBuffer */ + /* - OutputConnection */ + /* - 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_Channel & DAC_CR_CHX_BITOFFSET_MASK) + , + (DAC_InitStruct->TriggerSource + | DAC_InitStruct->WaveAutoGeneration + | DAC_InitStruct->WaveAutoGenerationConfig + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); + } + else + { + MODIFY_REG(DACx->CR, + (DAC_CR_TSEL1 + | DAC_CR_WAVE1 + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + , + (DAC_InitStruct->TriggerSource + | LL_DAC_WAVE_AUTO_GENERATION_NONE + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); + } + MODIFY_REG(DACx->MCR, + (DAC_MCR_MODE1_1 + | DAC_MCR_MODE1_0 + | DAC_MCR_MODE1_2 + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + , + (DAC_InitStruct->OutputBuffer + | DAC_InitStruct->OutputConnection + | DAC_InitStruct->OutputMode + ) << (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; + DAC_InitStruct->OutputConnection = LL_DAC_OUTPUT_CONNECT_GPIO; + DAC_InitStruct->OutputMode = LL_DAC_OUTPUT_MODE_NORMAL; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DAC1 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c new file mode 100644 index 0000000..5d18638 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c @@ -0,0 +1,400 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 "stm32l4xx_ll_dma.h" +#include "stm32l4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32L4xx_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)) + +#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) + +#if defined(DMAMUX1) +#define IS_LL_DMA_PERIPHREQUEST(__VALUE__) ((__VALUE__) <= 93U) +#else +#define IS_LL_DMA_PERIPHREQUEST(__VALUE__) (((__VALUE__) == LL_DMA_REQUEST_0) || \ + ((__VALUE__) == LL_DMA_REQUEST_1) || \ + ((__VALUE__) == LL_DMA_REQUEST_2) || \ + ((__VALUE__) == LL_DMA_REQUEST_3) || \ + ((__VALUE__) == LL_DMA_REQUEST_4) || \ + ((__VALUE__) == LL_DMA_REQUEST_5) || \ + ((__VALUE__) == LL_DMA_REQUEST_6) || \ + ((__VALUE__) == LL_DMA_REQUEST_7)) +#endif /* DMAMUX1 */ + +#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)) + +#if defined (DMA2) +#if defined (DMA2_Channel6) && defined (DMA2_Channel7) +#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \ + (((CHANNEL) == LL_DMA_CHANNEL_1) || \ + ((CHANNEL) == LL_DMA_CHANNEL_2) || \ + ((CHANNEL) == LL_DMA_CHANNEL_3) || \ + ((CHANNEL) == LL_DMA_CHANNEL_4) || \ + ((CHANNEL) == LL_DMA_CHANNEL_5) || \ + ((CHANNEL) == LL_DMA_CHANNEL_6) || \ + ((CHANNEL) == LL_DMA_CHANNEL_7))) || \ + (((INSTANCE) == DMA2) && \ + (((CHANNEL) == LL_DMA_CHANNEL_1) || \ + ((CHANNEL) == LL_DMA_CHANNEL_2) || \ + ((CHANNEL) == LL_DMA_CHANNEL_3) || \ + ((CHANNEL) == LL_DMA_CHANNEL_4) || \ + ((CHANNEL) == LL_DMA_CHANNEL_5) || \ + ((CHANNEL) == LL_DMA_CHANNEL_6) || \ + ((CHANNEL) == LL_DMA_CHANNEL_7)))) +#else +#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \ + (((CHANNEL) == LL_DMA_CHANNEL_1) || \ + ((CHANNEL) == LL_DMA_CHANNEL_2) || \ + ((CHANNEL) == LL_DMA_CHANNEL_3) || \ + ((CHANNEL) == LL_DMA_CHANNEL_4) || \ + ((CHANNEL) == LL_DMA_CHANNEL_5) || \ + ((CHANNEL) == LL_DMA_CHANNEL_6) || \ + ((CHANNEL) == LL_DMA_CHANNEL_7))) || \ + (((INSTANCE) == DMA2) && \ + (((CHANNEL) == LL_DMA_CHANNEL_1) || \ + ((CHANNEL) == LL_DMA_CHANNEL_2) || \ + ((CHANNEL) == LL_DMA_CHANNEL_3) || \ + ((CHANNEL) == LL_DMA_CHANNEL_4) || \ + ((CHANNEL) == LL_DMA_CHANNEL_5)))) +#endif +#else +#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \ + (((CHANNEL) == LL_DMA_CHANNEL_1)|| \ + ((CHANNEL) == LL_DMA_CHANNEL_2) || \ + ((CHANNEL) == LL_DMA_CHANNEL_3) || \ + ((CHANNEL) == LL_DMA_CHANNEL_4) || \ + ((CHANNEL) == LL_DMA_CHANNEL_5) || \ + ((CHANNEL) == LL_DMA_CHANNEL_6) || \ + ((CHANNEL) == LL_DMA_CHANNEL_7)))) +#endif +/** + * @} + */ + +/* 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 Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_7 + * @arg @ref LL_DMA_CHANNEL_ALL + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DMA registers are de-initialized + * - ERROR: DMA registers are not de-initialized + */ +ErrorStatus LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel) +{ + ErrorStatus status = SUCCESS; + DMA_Channel_TypeDef *tmp; + + /* Check the DMA Instance DMAx and Channel parameters*/ + assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel) || (Channel == LL_DMA_CHANNEL_ALL)); + + if (Channel == LL_DMA_CHANNEL_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); + } +#if defined(DMA2) + 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); + } +#endif + else + { + status = ERROR; + } + } + else + { + tmp = (DMA_Channel_TypeDef *)(__LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel)); + + /* Disable the selected DMAx_Channely */ + CLEAR_BIT(tmp->CCR, DMA_CCR_EN); + + /* Reset DMAx_Channely control register */ + WRITE_REG(tmp->CCR, 0U); + + /* Reset DMAx_Channely remaining bytes register */ + WRITE_REG(tmp->CNDTR, 0U); + + /* Reset DMAx_Channely peripheral address register */ + WRITE_REG(tmp->CPAR, 0U); + + /* Reset DMAx_Channely memory 0 address register */ + WRITE_REG(tmp->CMAR, 0U); + +#if defined(DMAMUX1) + /* Reset Request register field for DMAx Channel */ + LL_DMA_SetPeriphRequest(DMAx, Channel, LL_DMAMUX_REQ_MEM2MEM); +#else + /* Reset Request register field for DMAx Channel */ + LL_DMA_SetPeriphRequest(DMAx, Channel, LL_DMA_REQUEST_0); +#endif /* DMAMUX1 */ + + if (Channel == LL_DMA_CHANNEL_1) + { + /* Reset interrupt pending bits for DMAx Channel1 */ + LL_DMA_ClearFlag_GI1(DMAx); + } + else if (Channel == LL_DMA_CHANNEL_2) + { + /* Reset interrupt pending bits for DMAx Channel2 */ + LL_DMA_ClearFlag_GI2(DMAx); + } + else if (Channel == LL_DMA_CHANNEL_3) + { + /* Reset interrupt pending bits for DMAx Channel3 */ + LL_DMA_ClearFlag_GI3(DMAx); + } + else if (Channel == LL_DMA_CHANNEL_4) + { + /* Reset interrupt pending bits for DMAx Channel4 */ + LL_DMA_ClearFlag_GI4(DMAx); + } + else if (Channel == LL_DMA_CHANNEL_5) + { + /* Reset interrupt pending bits for DMAx Channel5 */ + LL_DMA_ClearFlag_GI5(DMAx); + } + + else if (Channel == LL_DMA_CHANNEL_6) + { + /* Reset interrupt pending bits for DMAx Channel6 */ + LL_DMA_ClearFlag_GI6(DMAx); + } + else if (Channel == LL_DMA_CHANNEL_7) + { + /* Reset interrupt pending bits for DMAx Channel7 */ + LL_DMA_ClearFlag_GI7(DMAx); + } + else + { + status = ERROR; + } + } + + return status; +} + +/** + * @brief Initialize the DMA registers according to the specified parameters in DMA_InitStruct. + * @note To convert DMAx_Channely Instance to DMAx Instance and Channely, use helper macros : + * @arg @ref __LL_DMA_GET_INSTANCE + * @arg @ref __LL_DMA_GET_CHANNEL + * @param DMAx DMAx Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_DMA_CHANNEL_1 + * @arg @ref LL_DMA_CHANNEL_2 + * @arg @ref LL_DMA_CHANNEL_3 + * @arg @ref LL_DMA_CHANNEL_4 + * @arg @ref LL_DMA_CHANNEL_5 + * @arg @ref LL_DMA_CHANNEL_6 + * @arg @ref LL_DMA_CHANNEL_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 + */ +ErrorStatus LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct) +{ + /* Check the DMA Instance DMAx and Channel parameters*/ + assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel)); + + /* 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_PERIPHREQUEST(DMA_InitStruct->PeriphRequest)); + assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority)); + + /*---------------------------- DMAx CCR Configuration ------------------------ + * Configure DMAx_Channely: data transfer direction, data transfer mode, + * peripheral and memory increment mode, + * data size alignment and priority level with parameters : + * - Direction: DMA_CCR_DIR and DMA_CCR_MEM2MEM bits + * - Mode: DMA_CCR_CIRC bit + * - PeriphOrM2MSrcIncMode: DMA_CCR_PINC bit + * - MemoryOrM2MDstIncMode: DMA_CCR_MINC bit + * - PeriphOrM2MSrcDataSize: DMA_CCR_PSIZE[1:0] bits + * - MemoryOrM2MDstDataSize: DMA_CCR_MSIZE[1:0] bits + * - Priority: DMA_CCR_PL[1:0] bits + */ + LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->Direction | \ + DMA_InitStruct->Mode | \ + DMA_InitStruct->PeriphOrM2MSrcIncMode | \ + DMA_InitStruct->MemoryOrM2MDstIncMode | \ + DMA_InitStruct->PeriphOrM2MSrcDataSize | \ + DMA_InitStruct->MemoryOrM2MDstDataSize | \ + DMA_InitStruct->Priority); + + /*-------------------------- DMAx CMAR Configuration ------------------------- + * Configure the memory or destination base address with parameter : + * - MemoryOrM2MDstAddress: DMA_CMAR_MA[31:0] bits + */ + LL_DMA_SetMemoryAddress(DMAx, Channel, DMA_InitStruct->MemoryOrM2MDstAddress); + + /*-------------------------- DMAx CPAR Configuration ------------------------- + * Configure the peripheral or source base address with parameter : + * - PeriphOrM2MSrcAddress: DMA_CPAR_PA[31:0] bits + */ + LL_DMA_SetPeriphAddress(DMAx, Channel, DMA_InitStruct->PeriphOrM2MSrcAddress); + + /*--------------------------- DMAx CNDTR Configuration ----------------------- + * Configure the peripheral base address with parameter : + * - NbData: DMA_CNDTR_NDT[15:0] bits + */ + LL_DMA_SetDataLength(DMAx, Channel, DMA_InitStruct->NbData); + +#if defined(DMAMUX1) + /*--------------------------- DMAMUXx CCR Configuration ---------------------- + * Configure the DMA request for DMA Channels on DMAMUX Channel x with parameter : + * - PeriphRequest: DMA_CxCR[7:0] bits + */ + LL_DMA_SetPeriphRequest(DMAx, Channel, DMA_InitStruct->PeriphRequest); +#else + /*--------------------------- DMAx CSELR Configuration ----------------------- + * Configure the DMA request for DMA instance on Channel x with parameter : + * - PeriphRequest: DMA_CSELR[31:0] bits + */ + LL_DMA_SetPeriphRequest(DMAx, Channel, DMA_InitStruct->PeriphRequest); +#endif /* DMAMUX1 */ + + 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; +#if defined(DMAMUX1) + DMA_InitStruct->PeriphRequest = LL_DMAMUX_REQ_MEM2MEM; +#else + DMA_InitStruct->PeriphRequest = LL_DMA_REQUEST_0; +#endif /* DMAMUX1 */ + DMA_InitStruct->Priority = LL_DMA_PRIORITY_LOW; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMA1 || DMA2 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c new file mode 100644 index 0000000..8d28066 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c @@ -0,0 +1,288 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_exti.c + * @author MCD Application Team + * @brief EXTI 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 "stm32l4xx_ll_exti.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32L4xx_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_LINE_32_63(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_32_63) == 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: + * - 0x00: EXTI registers are de-initialized + */ +uint32_t LL_EXTI_DeInit(void) +{ + /* Interrupt mask register set to default reset values */ + LL_EXTI_WriteReg(IMR1, 0xFF820000U); + /* Event mask register set to default reset values */ + LL_EXTI_WriteReg(EMR1, 0x00000000U); + /* Rising Trigger selection register set to default reset values */ + LL_EXTI_WriteReg(RTSR1, 0x00000000U); + /* Falling Trigger selection register set to default reset values */ + LL_EXTI_WriteReg(FTSR1, 0x00000000U); + /* Software interrupt event register set to default reset values */ + LL_EXTI_WriteReg(SWIER1, 0x00000000U); + /* Pending register clear */ + LL_EXTI_WriteReg(PR1, 0x007DFFFFU); + + /* Interrupt mask register 2 set to default reset values */ +#if defined(LL_EXTI_LINE_40) + LL_EXTI_WriteReg(IMR2, 0x00000187U); +#else + LL_EXTI_WriteReg(IMR2, 0x00000087U); +#endif + /* Event mask register 2 set to default reset values */ + LL_EXTI_WriteReg(EMR2, 0x00000000U); + /* Rising Trigger selection register 2 set to default reset values */ + LL_EXTI_WriteReg(RTSR2, 0x00000000U); + /* Falling Trigger selection register 2 set to default reset values */ + LL_EXTI_WriteReg(FTSR2, 0x00000000U); + /* Software interrupt event register 2 set to default reset values */ + LL_EXTI_WriteReg(SWIER2, 0x00000000U); + /* Pending register 2 clear */ + LL_EXTI_WriteReg(PR2, 0x00000078U); + + return 0x00u; +} + +/** + * @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: + * - 0x00: EXTI registers are initialized + * - any other value : wrong configuration + */ +uint32_t LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct) +{ + uint32_t status = 0x00u; + + /* Check the parameters */ + assert_param(IS_LL_EXTI_LINE_0_31(EXTI_InitStruct->Line_0_31)); + assert_param(IS_LL_EXTI_LINE_32_63(EXTI_InitStruct->Line_32_63)); + 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 = 0x01u; + 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 |= 0x02u; + break; + } + } + } + /* Configure EXTI Lines in range from 32 to 63 */ + if (EXTI_InitStruct->Line_32_63 != LL_EXTI_LINE_NONE) + { + switch (EXTI_InitStruct->Mode) + { + case LL_EXTI_MODE_IT: + /* First Disable Event on provided Lines */ + LL_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63); + /* Then Enable IT on provided Lines */ + LL_EXTI_EnableIT_32_63(EXTI_InitStruct->Line_32_63); + break; + case LL_EXTI_MODE_EVENT: + /* First Disable IT on provided Lines */ + LL_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63); + /* Then Enable Event on provided Lines */ + LL_EXTI_EnableEvent_32_63(EXTI_InitStruct->Line_32_63); + break; + case LL_EXTI_MODE_IT_EVENT: + /* Directly Enable IT & Event on provided Lines */ + LL_EXTI_EnableIT_32_63(EXTI_InitStruct->Line_32_63); + LL_EXTI_EnableEvent_32_63(EXTI_InitStruct->Line_32_63); + break; + default: + status |= 0x04u; + 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_32_63(EXTI_InitStruct->Line_32_63); + /* Then Enable IT on provided Lines */ + LL_EXTI_EnableRisingTrig_32_63(EXTI_InitStruct->Line_32_63); + break; + case LL_EXTI_TRIGGER_FALLING: + /* First Disable Rising Trigger on provided Lines */ + LL_EXTI_DisableRisingTrig_32_63(EXTI_InitStruct->Line_32_63); + /* Then Enable Falling Trigger on provided Lines */ + LL_EXTI_EnableFallingTrig_32_63(EXTI_InitStruct->Line_32_63); + break; + case LL_EXTI_TRIGGER_RISING_FALLING: + LL_EXTI_EnableRisingTrig_32_63(EXTI_InitStruct->Line_32_63); + LL_EXTI_EnableFallingTrig_32_63(EXTI_InitStruct->Line_32_63); + 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); + /* De-configure EXTI Lines in range from 32 to 63 */ + LL_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63); + LL_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63); + } + + 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->Line_32_63 = 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/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c new file mode 100644 index 0000000..c3dd30c --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c @@ -0,0 +1,293 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 "stm32l4xx_ll_gpio.h" +#include "stm32l4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) + +/** @addtogroup GPIO_LL + * @{ + */ +/** MISRA C:2012 deviation rule has been granted for following rules: + * Rule-12.2 - Medium: RHS argument is in interval [0,INF] which is out of + * range of the shift operator in following API : + * LL_GPIO_Init + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup GPIO_LL_Private_Macros + * @{ + */ +#define IS_LL_GPIO_PIN(__VALUE__) (((0x00u) < (__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_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOA); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOA); + } + else if (GPIOx == GPIOB) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOB); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOB); + } + else if (GPIOx == GPIOC) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOC); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOC); + } +#if defined(GPIOD) + else if (GPIOx == GPIOD) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOD); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOD); + } +#endif /* GPIOD */ +#if defined(GPIOE) + else if (GPIOx == GPIOE) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOE); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOE); + } +#endif /* GPIOE */ +#if defined(GPIOF) + else if (GPIOx == GPIOF) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOF); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOF); + } +#endif /* GPIOF */ +#if defined(GPIOG) + else if (GPIOx == GPIOG) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOG); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOG); + } +#endif /* GPIOG */ +#if defined(GPIOH) + else if (GPIOx == GPIOH) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOH); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOH); + } +#endif /* GPIOH */ +#if defined(GPIOI) + else if (GPIOx == GPIOI) + { + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOI); + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOI); + } +#endif /* GPIOI */ + 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; + uint32_t currentpin; + + /* 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) != 0x00u) + { + /* Get current io position */ + currentpin = (GPIO_InitStruct->Pin) & (0x00000001uL << pinpos); + + if (currentpin != 0x00u) + { + 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, GPIO_InitStruct->Pin, 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 (currentpin < LL_GPIO_PIN_8) + { + 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) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_i2c.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_i2c.c new file mode 100644 index 0000000..6f34239 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_i2c.c @@ -0,0 +1,244 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_i2c.c + * @author MCD Application Team + * @brief I2C 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 "stm32l4xx_ll_i2c.h" +#include "stm32l4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (I2C1) || defined (I2C2) || defined (I2C3) || defined (I2C4) + +/** @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_ANALOG_FILTER(__VALUE__) (((__VALUE__) == LL_I2C_ANALOGFILTER_ENABLE) || \ + ((__VALUE__) == LL_I2C_ANALOGFILTER_DISABLE)) + +#define IS_LL_I2C_DIGITAL_FILTER(__VALUE__) ((__VALUE__) <= 0x0000000FU) + +#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 + */ +ErrorStatus LL_I2C_DeInit(const 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); + } +#if defined(I2C2) + 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); + + } +#endif /* I2C2 */ + 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); + } +#if defined(I2C4) + else if (I2Cx == I2C4) + { + /* Force reset of I2C clock */ + LL_APB1_GRP2_ForceReset(LL_APB1_GRP2_PERIPH_I2C4); + + /* Release reset of I2C clock */ + LL_APB1_GRP2_ReleaseReset(LL_APB1_GRP2_PERIPH_I2C4); + } +#endif /* I2C4 */ + 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 + */ +ErrorStatus LL_I2C_Init(I2C_TypeDef *I2Cx, const LL_I2C_InitTypeDef *I2C_InitStruct) +{ + /* 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_ANALOG_FILTER(I2C_InitStruct->AnalogFilter)); + assert_param(IS_LL_I2C_DIGITAL_FILTER(I2C_InitStruct->DigitalFilter)); + 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); + + /*---------------------------- I2Cx CR1 Configuration ------------------------ + * Configure the analog and digital noise filters with parameters : + * - AnalogFilter: I2C_CR1_ANFOFF bit + * - DigitalFilter: I2C_CR1_DNF[3:0] bits + */ + LL_I2C_ConfigFilters(I2Cx, I2C_InitStruct->AnalogFilter, I2C_InitStruct->DigitalFilter); + + /*---------------------------- I2Cx TIMINGR Configuration -------------------- + * Configure the SDA setup, hold time and the SCL high, low period with parameter : + * - Timing: I2C_TIMINGR_PRESC[3:0], I2C_TIMINGR_SCLDEL[3:0], I2C_TIMINGR_SDADEL[3:0], + * I2C_TIMINGR_SCLH[7:0] and I2C_TIMINGR_SCLL[7:0] bits + */ + LL_I2C_SetTiming(I2Cx, I2C_InitStruct->Timing); + + /* Enable the selected I2Cx Peripheral */ + LL_I2C_Enable(I2Cx); + + /*---------------------------- I2Cx OAR1 Configuration ----------------------- + * Disable, Configure and Enable I2Cx device own address 1 with parameters : + * - OwnAddress1: I2C_OAR1_OA1[9:0] bits + * - OwnAddrSize: I2C_OAR1_OA1MODE bit + */ + LL_I2C_DisableOwnAddress1(I2Cx); + LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1, I2C_InitStruct->OwnAddrSize); + + /* OwnAdress1 == 0 is reserved for General Call address */ + if (I2C_InitStruct->OwnAddress1 != 0U) + { + LL_I2C_EnableOwnAddress1(I2Cx); + } + + /*---------------------------- I2Cx MODE Configuration ----------------------- + * Configure I2Cx peripheral mode with parameter : + * - PeripheralMode: I2C_CR1_SMBDEN and I2C_CR1_SMBHEN bits + */ + LL_I2C_SetMode(I2Cx, I2C_InitStruct->PeripheralMode); + + /*---------------------------- 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->Timing = 0U; + I2C_InitStruct->AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; + I2C_InitStruct->DigitalFilter = 0U; + I2C_InitStruct->OwnAddress1 = 0U; + I2C_InitStruct->TypeAcknowledge = LL_I2C_NACK; + I2C_InitStruct->OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* I2C1 || I2C2 || I2C3 || I2C4 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c new file mode 100644 index 0000000..8907e5d --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c @@ -0,0 +1,82 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 "stm32l4xx_ll_pwr.h" +#include "stm32l4xx_ll_bus.h" + +/** @addtogroup STM32L4xx_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/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c new file mode 100644 index 0000000..f7f6d08 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c @@ -0,0 +1,2039 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 "stm32l4xx_ll_rcc.h" +#ifdef USE_FULL_ASSERT + #include "stm32_assert.h" +#else + #define assert_param(expr) ((void)0U) +#endif +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(RCC) + +/** @addtogroup RCC_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RCC_LL_Private_Macros + * @{ + */ +#if defined(RCC_CCIPR_USART3SEL) +#define IS_LL_RCC_USART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USART1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_USART2_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_USART3_CLKSOURCE)) +#else +#define IS_LL_RCC_USART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USART1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_USART2_CLKSOURCE)) + +#endif /* RCC_CCIPR_USART3SEL */ +#if defined(RCC_CCIPR_UART4SEL) && defined(RCC_CCIPR_UART5SEL) +#define IS_LL_RCC_UART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_UART4_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_UART5_CLKSOURCE)) +#elif defined(RCC_CCIPR_UART4SEL) +#define IS_LL_RCC_UART_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_UART4_CLKSOURCE) +#elif defined(RCC_CCIPR_UART5SEL) +#define IS_LL_RCC_UART_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_UART5_CLKSOURCE) +#endif /* RCC_CCIPR_UART4SEL && RCC_CCIPR_UART5SEL*/ + +#define IS_LL_RCC_LPUART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPUART1_CLKSOURCE)) + +#if defined(RCC_CCIPR_I2C2SEL) && defined(RCC_CCIPR_I2C3SEL) && defined(RCC_CCIPR2_I2C4SEL) +#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2C2_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2C4_CLKSOURCE)) +#elif defined(RCC_CCIPR_I2C2SEL) && defined(RCC_CCIPR_I2C3SEL) +#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2C2_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE)) + +#elif !defined(RCC_CCIPR_I2C2SEL) && defined(RCC_CCIPR_I2C3SEL) +#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE)) + +#else +#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) + +#endif /* RCC_CCIPR_I2C2SEL && RCC_CCIPR_I2C3SEL && RCC_CCIPR2_I2C4SEL */ +#define IS_LL_RCC_LPTIM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPTIM1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_LPTIM2_CLKSOURCE)) + +#if defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI2SEL) +#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SAI1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_SAI2_CLKSOURCE)) +#elif defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR2_SAI1SEL) +#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_SAI1_CLKSOURCE) +#endif /* RCC_CCIPR_SAI2SEL RCC_CCIPR2_SAI2SEL ||*/ + +#if defined(SDMMC1) +#if defined(RCC_CCIPR2_SDMMCSEL) +#define IS_LL_RCC_SDMMC_KERNELCLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SDMMC1_KERNELCLKSOURCE)) +#endif /* RCC_CCIPR2_SDMMCSEL */ + +#define IS_LL_RCC_SDMMC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SDMMC1_CLKSOURCE)) +#endif /* SDMMC1 */ + +#define IS_LL_RCC_RNG_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_RNG_CLKSOURCE)) + +#if defined(USB_OTG_FS) || defined(USB) +#define IS_LL_RCC_USB_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USB_CLKSOURCE)) +#endif /* USB_OTG_FS || USB */ + +#define IS_LL_RCC_ADC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_ADC_CLKSOURCE)) + +#if defined(SWPMI1) +#define IS_LL_RCC_SWPMI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SWPMI1_CLKSOURCE)) +#endif /* SWPMI1 */ + +#if defined(DFSDM1_Channel0) +#define IS_LL_RCC_DFSDM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_CLKSOURCE)) +#if defined(RCC_CCIPR2_DFSDM1SEL) +#define IS_LL_RCC_DFSDM_AUDIO_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_AUDIO_CLKSOURCE)) +#endif /* RCC_CCIPR2_DFSDM1SEL */ +#endif /* DFSDM1_Channel0 */ + +#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(OCTOSPI1) +#define IS_LL_RCC_OCTOSPI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_OCTOSPI_CLKSOURCE)) +#endif /* OCTOSPI */ + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup RCC_LL_Private_Functions RCC Private functions + * @{ + */ +static uint32_t RCC_GetSystemClockFreq(void); +static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency); +static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency); +static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency); +static uint32_t RCC_PLL_GetFreqDomain_SYS(void); +#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI1SEL) || defined(RCC_CCIPR2_SAI2SEL) +static uint32_t RCC_PLL_GetFreqDomain_SAI(void); +#endif +static uint32_t RCC_PLL_GetFreqDomain_48M(void); +#if defined(RCC_PLLSAI1_SUPPORT) +static uint32_t RCC_PLLSAI1_GetFreqDomain_SAI(void); +static uint32_t RCC_PLLSAI1_GetFreqDomain_48M(void); +static uint32_t RCC_PLLSAI1_GetFreqDomain_ADC(void); +#endif /* RCC_PLLSAI1_SUPPORT */ +#if defined(RCC_PLLSAI2_SUPPORT) +static uint32_t RCC_PLLSAI2_GetFreqDomain_SAI(void); +#if defined(LTDC) +static uint32_t RCC_PLLSAI2_GetFreqDomain_LTDC(void); +#else +static uint32_t RCC_PLLSAI2_GetFreqDomain_ADC(void); +#endif /* LTDC */ +#if defined(DSI) +static uint32_t RCC_PLLSAI2_GetFreqDomain_DSI(void); +#endif /* DSI */ +#endif /*RCC_PLLSAI2_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: + * - MSI ON and used as system clock source + * - HSE, HSI, PLL, PLLSAI1 and PLLSAI2 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 MSION bit */ + LL_RCC_MSI_Enable(); + + /* Insure MSIRDY bit is set before writing default MSIRANGE value */ + while (LL_RCC_MSI_IsReady() == 0U) + { + } + + /* Set MSIRANGE default value */ + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6); + + /* Set MSITRIM bits to the reset value*/ + LL_RCC_MSI_SetCalibTrimming(0); + + /* Set HSITRIM bits to the reset value*/ +#if defined(RCC_ICSCR_HSITRIM_6) + LL_RCC_HSI_SetCalibTrimming(0x40U); +#else + LL_RCC_HSI_SetCalibTrimming(0x10U); +#endif /* RCC_ICSCR_HSITRIM_6 */ + + /* Reset CFGR register */ + LL_RCC_WriteReg(CFGR, 0x00000000U); + + /* Read CR register */ + vl_mask = LL_RCC_ReadReg(CR); + + /* Reset HSION, HSIKERON, HSIASFS, HSEON, PLLON bits */ + CLEAR_BIT(vl_mask, + (RCC_CR_HSION | RCC_CR_HSIASFS | RCC_CR_HSIKERON | RCC_CR_HSEON | RCC_CR_PLLON)); + +#if defined(RCC_PLLSAI1_SUPPORT) + /* Reset PLLSAI1ON bit */ + CLEAR_BIT(vl_mask, RCC_CR_PLLSAI1ON); +#endif /*RCC_PLLSAI1_SUPPORT*/ + +#if defined(RCC_PLLSAI2_SUPPORT) + /* Reset PLLSAI2ON bit */ + CLEAR_BIT(vl_mask, RCC_CR_PLLSAI2ON); +#endif /*RCC_PLLSAI2_SUPPORT*/ + + /* Write new value in CR register */ + LL_RCC_WriteReg(CR, vl_mask); + +#if defined(RCC_PLLSAI2_SUPPORT) + /* Wait for PLLRDY, PLLSAI1RDY and PLLSAI2RDY bits to be reset */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U) + { + } +#elif defined(RCC_PLLSAI1_SUPPORT) + /* Wait for PLLRDY and PLLSAI1RDY to be reset */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U) + { + } +#else + /* Wait for PLLRDY bit to be reset */ + while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U) + { + } +#endif + + /* Reset PLLCFGR register */ + LL_RCC_WriteReg(PLLCFGR, 16U << RCC_PLLCFGR_PLLN_Pos); + +#if defined(RCC_PLLSAI1_SUPPORT) + /* Reset PLLSAI1CFGR register */ + LL_RCC_WriteReg(PLLSAI1CFGR, 16U << RCC_PLLSAI1CFGR_PLLSAI1N_Pos); +#endif /*RCC_PLLSAI1_SUPPORT*/ + +#if defined(RCC_PLLSAI2_SUPPORT) + /* Reset PLLSAI2CFGR register */ + LL_RCC_WriteReg(PLLSAI2CFGR, 16U << RCC_PLLSAI2CFGR_PLLSAI2N_Pos); +#endif /*RCC_PLLSAI2_SUPPORT*/ + + /* Reset HSEBYP bit */ + LL_RCC_HSE_DisableBypass(); + + /* Disable all interrupts */ + LL_RCC_WriteReg(CIER, 0x00000000U); + + /* Clear all interrupt flags */ + vl_mask = RCC_CICR_LSIRDYC | RCC_CICR_LSERDYC | RCC_CICR_MSIRDYC | RCC_CICR_HSIRDYC | RCC_CICR_HSERDYC | RCC_CICR_PLLRDYC | \ + RCC_CICR_CSSC | RCC_CICR_LSECSSC; +#if defined(RCC_HSI48_SUPPORT) + vl_mask |= RCC_CICR_HSI48RDYC; +#endif +#if defined(RCC_PLLSAI1_SUPPORT) + vl_mask |= RCC_CICR_PLLSAI1RDYC; +#endif +#if defined(RCC_PLLSAI2_SUPPORT) + vl_mask |= RCC_CICR_PLLSAI2RDYC; +#endif + LL_RCC_WriteReg(CICR, vl_mask); + + /* Clear reset flags */ + LL_RCC_ClearResetFlags(); + + 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 MSI, function returns values based on MSI_VALUE(*) + * @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(**) or MSI_VALUE(*) multiplied/divided by the PLL factors. + * @note (*) MSI_VALUE is a constant defined in this file (default value + * 4 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * @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 + * 8 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * @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); +} + +/** + * @brief Return USARTx clock frequency + * @param USARTxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_USART1_CLKSOURCE + * @arg @ref LL_RCC_USART2_CLKSOURCE + * @arg @ref LL_RCC_USART3_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval USART clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready + */ +uint32_t LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource) +{ + uint32_t usart_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_USART_CLKSOURCE(USARTxSource)); + + if (USARTxSource == LL_RCC_USART1_CLKSOURCE) + { + /* USART1CLK clock frequency */ + switch (LL_RCC_GetUSARTClockSource(USARTxSource)) + { + case LL_RCC_USART1_CLKSOURCE_SYSCLK: /* USART1 Clock is System Clock */ + usart_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_USART1_CLKSOURCE_HSI: /* USART1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + usart_frequency = HSI_VALUE; + } + break; + + case LL_RCC_USART1_CLKSOURCE_LSE: /* USART1 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + usart_frequency = LSE_VALUE; + } + break; + + case LL_RCC_USART1_CLKSOURCE_PCLK2: /* USART1 Clock is PCLK2 */ + usart_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } + else if (USARTxSource == LL_RCC_USART2_CLKSOURCE) + { + /* USART2CLK clock frequency */ + switch (LL_RCC_GetUSARTClockSource(USARTxSource)) + { + case LL_RCC_USART2_CLKSOURCE_SYSCLK: /* USART2 Clock is System Clock */ + usart_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_USART2_CLKSOURCE_HSI: /* USART2 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + usart_frequency = HSI_VALUE; + } + break; + + case LL_RCC_USART2_CLKSOURCE_LSE: /* USART2 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + usart_frequency = LSE_VALUE; + } + break; + + case LL_RCC_USART2_CLKSOURCE_PCLK1: /* USART2 Clock is PCLK1 */ + usart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } + else + { +#if defined(RCC_CCIPR_USART3SEL) + if (USARTxSource == LL_RCC_USART3_CLKSOURCE) + { + /* USART3CLK clock frequency */ + switch (LL_RCC_GetUSARTClockSource(USARTxSource)) + { + case LL_RCC_USART3_CLKSOURCE_SYSCLK: /* USART3 Clock is System Clock */ + usart_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_USART3_CLKSOURCE_HSI: /* USART3 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + usart_frequency = HSI_VALUE; + } + break; + + case LL_RCC_USART3_CLKSOURCE_LSE: /* USART3 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + usart_frequency = LSE_VALUE; + } + break; + + case LL_RCC_USART3_CLKSOURCE_PCLK1: /* USART3 Clock is PCLK1 */ + usart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } +#endif /* RCC_CCIPR_USART3SEL */ + } + return usart_frequency; +} + +#if defined(RCC_CCIPR_UART4SEL) || defined(RCC_CCIPR_UART5SEL) +/** + * @brief Return UARTx clock frequency + * @param UARTxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_UART4_CLKSOURCE + * @arg @ref LL_RCC_UART5_CLKSOURCE + * @retval UART clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready + */ +uint32_t LL_RCC_GetUARTClockFreq(uint32_t UARTxSource) +{ + uint32_t uart_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_UART_CLKSOURCE(UARTxSource)); + +#if defined(RCC_CCIPR_UART4SEL) + if (UARTxSource == LL_RCC_UART4_CLKSOURCE) + { + /* UART4CLK clock frequency */ + switch (LL_RCC_GetUARTClockSource(UARTxSource)) + { + case LL_RCC_UART4_CLKSOURCE_SYSCLK: /* UART4 Clock is System Clock */ + uart_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_UART4_CLKSOURCE_HSI: /* UART4 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + uart_frequency = HSI_VALUE; + } + break; + + case LL_RCC_UART4_CLKSOURCE_LSE: /* UART4 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + uart_frequency = LSE_VALUE; + } + break; + + case LL_RCC_UART4_CLKSOURCE_PCLK1: /* UART4 Clock is PCLK1 */ + uart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } +#endif /* RCC_CCIPR_UART4SEL */ + +#if defined(RCC_CCIPR_UART5SEL) + if (UARTxSource == LL_RCC_UART5_CLKSOURCE) + { + /* UART5CLK clock frequency */ + switch (LL_RCC_GetUARTClockSource(UARTxSource)) + { + case LL_RCC_UART5_CLKSOURCE_SYSCLK: /* UART5 Clock is System Clock */ + uart_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_UART5_CLKSOURCE_HSI: /* UART5 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + uart_frequency = HSI_VALUE; + } + break; + + case LL_RCC_UART5_CLKSOURCE_LSE: /* UART5 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + uart_frequency = LSE_VALUE; + } + break; + + case LL_RCC_UART5_CLKSOURCE_PCLK1: /* UART5 Clock is PCLK1 */ + uart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } +#endif /* RCC_CCIPR_UART5SEL */ + + return uart_frequency; +} +#endif /* RCC_CCIPR_UART4SEL || RCC_CCIPR_UART5SEL */ + +/** + * @brief Return I2Cx clock frequency + * @param I2CxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_I2C1_CLKSOURCE + * @arg @ref LL_RCC_I2C2_CLKSOURCE (*) + * @arg @ref LL_RCC_I2C3_CLKSOURCE + * @arg @ref LL_RCC_I2C4_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval I2C clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that HSI oscillator is not ready + */ +uint32_t LL_RCC_GetI2CClockFreq(uint32_t I2CxSource) +{ + uint32_t i2c_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_I2C_CLKSOURCE(I2CxSource)); + + if (I2CxSource == LL_RCC_I2C1_CLKSOURCE) + { + /* I2C1 CLK clock frequency */ + switch (LL_RCC_GetI2CClockSource(I2CxSource)) + { + case LL_RCC_I2C1_CLKSOURCE_SYSCLK: /* I2C1 Clock is System Clock */ + i2c_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_I2C1_CLKSOURCE_HSI: /* I2C1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + i2c_frequency = HSI_VALUE; + } + break; + + case LL_RCC_I2C1_CLKSOURCE_PCLK1: /* I2C1 Clock is PCLK1 */ + i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } +#if defined(RCC_CCIPR_I2C2SEL) + else if (I2CxSource == LL_RCC_I2C2_CLKSOURCE) + { + /* I2C2 CLK clock frequency */ + switch (LL_RCC_GetI2CClockSource(I2CxSource)) + { + case LL_RCC_I2C2_CLKSOURCE_SYSCLK: /* I2C2 Clock is System Clock */ + i2c_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_I2C2_CLKSOURCE_HSI: /* I2C2 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + i2c_frequency = HSI_VALUE; + } + break; + + case LL_RCC_I2C2_CLKSOURCE_PCLK1: /* I2C2 Clock is PCLK1 */ + i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } +#endif /*RCC_CCIPR_I2C2SEL*/ + else + { + if (I2CxSource == LL_RCC_I2C3_CLKSOURCE) + { + /* I2C3 CLK clock frequency */ + switch (LL_RCC_GetI2CClockSource(I2CxSource)) + { + case LL_RCC_I2C3_CLKSOURCE_SYSCLK: /* I2C3 Clock is System Clock */ + i2c_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_I2C3_CLKSOURCE_HSI: /* I2C3 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + i2c_frequency = HSI_VALUE; + } + break; + + case LL_RCC_I2C3_CLKSOURCE_PCLK1: /* I2C3 Clock is PCLK1 */ + i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } +#if defined(RCC_CCIPR2_I2C4SEL) + else + { + if (I2CxSource == LL_RCC_I2C4_CLKSOURCE) + { + /* I2C4 CLK clock frequency */ + switch (LL_RCC_GetI2CClockSource(I2CxSource)) + { + case LL_RCC_I2C4_CLKSOURCE_SYSCLK: /* I2C4 Clock is System Clock */ + i2c_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_I2C4_CLKSOURCE_HSI: /* I2C4 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + i2c_frequency = HSI_VALUE; + } + break; + + case LL_RCC_I2C4_CLKSOURCE_PCLK1: /* I2C4 Clock is PCLK1 */ + i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } + } +#endif /*RCC_CCIPR2_I2C4SEL*/ + } + + return i2c_frequency; +} + + +/** + * @brief Return LPUARTx clock frequency + * @param LPUARTxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_LPUART1_CLKSOURCE + * @retval LPUART clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready + */ +uint32_t LL_RCC_GetLPUARTClockFreq(uint32_t LPUARTxSource) +{ + uint32_t lpuart_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_LPUART_CLKSOURCE(LPUARTxSource)); + + /* LPUART1CLK clock frequency */ + switch (LL_RCC_GetLPUARTClockSource(LPUARTxSource)) + { + case LL_RCC_LPUART1_CLKSOURCE_SYSCLK: /* LPUART1 Clock is System Clock */ + lpuart_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_LPUART1_CLKSOURCE_HSI: /* LPUART1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + lpuart_frequency = HSI_VALUE; + } + break; + + case LL_RCC_LPUART1_CLKSOURCE_LSE: /* LPUART1 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + lpuart_frequency = LSE_VALUE; + } + break; + + case LL_RCC_LPUART1_CLKSOURCE_PCLK1: /* LPUART1 Clock is PCLK1 */ + lpuart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + + return lpuart_frequency; +} + +/** + * @brief Return LPTIMx clock frequency + * @param LPTIMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE + * @arg @ref LL_RCC_LPTIM2_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() != 0U) + { +#if defined(RCC_CSR_LSIPREDIV) + if (LL_RCC_LSI_GetPrediv() == LL_RCC_LSI_PREDIV_128) + { + lptim_frequency = LSI_VALUE / 128U; + } + else +#endif /* RCC_CSR_LSIPREDIV */ + { + lptim_frequency = LSI_VALUE; + } + } + break; + + case LL_RCC_LPTIM1_CLKSOURCE_HSI: /* LPTIM1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + lptim_frequency = HSI_VALUE; + } + break; + + case LL_RCC_LPTIM1_CLKSOURCE_LSE: /* LPTIM1 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + lptim_frequency = LSE_VALUE; + } + break; + + case LL_RCC_LPTIM1_CLKSOURCE_PCLK1: /* LPTIM1 Clock is PCLK1 */ + lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } + else + { + if (LPTIMxSource == LL_RCC_LPTIM2_CLKSOURCE) + { + /* LPTIM2CLK clock frequency */ + switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource)) + { + case LL_RCC_LPTIM2_CLKSOURCE_LSI: /* LPTIM2 Clock is LSI Osc. */ + if (LL_RCC_LSI_IsReady() != 0U) + { +#if defined(RCC_CSR_LSIPREDIV) + if (LL_RCC_LSI_GetPrediv() == LL_RCC_LSI_PREDIV_128) + { + lptim_frequency = LSI_VALUE / 128U; + } + else +#endif /* RCC_CSR_LSIPREDIV */ + { + lptim_frequency = LSI_VALUE; + } + } + break; + + case LL_RCC_LPTIM2_CLKSOURCE_HSI: /* LPTIM2 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady() != 0U) + { + lptim_frequency = HSI_VALUE; + } + break; + + case LL_RCC_LPTIM2_CLKSOURCE_LSE: /* LPTIM2 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady() != 0U) + { + lptim_frequency = LSE_VALUE; + } + break; + + case LL_RCC_LPTIM2_CLKSOURCE_PCLK1: /* LPTIM2 Clock is PCLK1 */ + lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + } + } + + return lptim_frequency; +} + +#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI1SEL) || defined(RCC_CCIPR2_SAI2SEL) +/** + * @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 (*) + * + * (*) value not defined in all devices. + * @retval SAI clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that PLL 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 (SAIxSource == LL_RCC_SAI1_CLKSOURCE) + { + /* SAI1CLK clock frequency */ + switch (LL_RCC_GetSAIClockSource(SAIxSource)) + { + case LL_RCC_SAI1_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SAI1 clock source */ + if (LL_RCC_PLLSAI1_IsReady() != 0U) + { + if (LL_RCC_PLLSAI1_IsEnabledDomain_SAI() != 0U) + { + sai_frequency = RCC_PLLSAI1_GetFreqDomain_SAI(); + } + } + break; + +#if defined(RCC_PLLSAI2_SUPPORT) + case LL_RCC_SAI1_CLKSOURCE_PLLSAI2: /* PLLSAI2 clock used as SAI1 clock source */ + if (LL_RCC_PLLSAI2_IsReady() != 0U) + { + if (LL_RCC_PLLSAI2_IsEnabledDomain_SAI() != 0U) + { + sai_frequency = RCC_PLLSAI2_GetFreqDomain_SAI(); + } + } + break; + +#endif /* RCC_PLLSAI2_SUPPORT */ + case LL_RCC_SAI1_CLKSOURCE_PLL: /* PLL clock used as SAI1 clock source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_SAI() != 0U) + { + sai_frequency = RCC_PLL_GetFreqDomain_SAI(); + } + } + break; + + case LL_RCC_SAI1_CLKSOURCE_PIN: /* External input clock used as SAI1 clock source */ + sai_frequency = EXTERNAL_SAI1_CLOCK_VALUE; + break; + + default: + break; + } + } + else + { +#if defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI2SEL) + if (SAIxSource == LL_RCC_SAI2_CLKSOURCE) + { + /* SAI2CLK clock frequency */ + switch (LL_RCC_GetSAIClockSource(SAIxSource)) + { + case LL_RCC_SAI2_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SAI2 clock source */ + if (LL_RCC_PLLSAI1_IsReady() != 0U) + { + if (LL_RCC_PLLSAI1_IsEnabledDomain_SAI() != 0U) + { + sai_frequency = RCC_PLLSAI1_GetFreqDomain_SAI(); + } + } + break; + +#if defined(RCC_PLLSAI2_SUPPORT) + case LL_RCC_SAI2_CLKSOURCE_PLLSAI2: /* PLLSAI2 clock used as SAI2 clock source */ + if (LL_RCC_PLLSAI2_IsReady() != 0U) + { + if (LL_RCC_PLLSAI2_IsEnabledDomain_SAI() != 0U) + { + sai_frequency = RCC_PLLSAI2_GetFreqDomain_SAI(); + } + } + break; + +#endif /* RCC_PLLSAI2_SUPPORT */ + case LL_RCC_SAI2_CLKSOURCE_PLL: /* PLL clock used as SAI2 clock source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_SAI() != 0U) + { + sai_frequency = RCC_PLL_GetFreqDomain_SAI(); + } + } + break; + + case LL_RCC_SAI2_CLKSOURCE_PIN: /* External input clock used as SAI2 clock source */ + sai_frequency = EXTERNAL_SAI2_CLOCK_VALUE; + break; + + default: + break; + } + } +#endif /* RCC_CCIPR_SAI2SEL || RCC_CCIPR2_SAI2SEL */ + } + + return sai_frequency; +} +#endif /* RCC_CCIPR_SAI1SEL || RCC_CCIPR_SAI2SEL || RCC_CCIPR2_SAI1SEL || RCC_CCIPR2_SAI2SEL*/ + +#if defined(SDMMC1) +#if defined(RCC_CCIPR2_SDMMCSEL) +/** + * @brief Return SDMMCx kernel clock frequency + * @param SDMMCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE + * @retval SDMMC clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready + * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected + */ +uint32_t LL_RCC_GetSDMMCKernelClockFreq(uint32_t SDMMCxSource) +{ + uint32_t sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_SDMMC_KERNELCLKSOURCE(SDMMCxSource)); + + /* SDMMC1CLK kernel clock frequency */ + switch (LL_RCC_GetSDMMCKernelClockSource(SDMMCxSource)) + { + case LL_RCC_SDMMC1_KERNELCLKSOURCE_48CLK: /* 48MHz clock from internal multiplexor used as SDMMC1 clock source */ + sdmmc_frequency = LL_RCC_GetSDMMCClockFreq(LL_RCC_SDMMC1_CLKSOURCE); + break; + + case LL_RCC_SDMMC1_KERNELCLKSOURCE_PLLP: /* PLL "P" output (PLLSAI3CLK) clock used as SDMMC1 clock source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_SAI() != 0U) + { + sdmmc_frequency = RCC_PLL_GetFreqDomain_SAI(); + } + } + break; + + default: + sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NA; + break; + } + + return sdmmc_frequency; +} +#endif + +/** + * @brief Return SDMMCx clock frequency + * @param SDMMCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SDMMC1_CLKSOURCE + * @retval SDMMC clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready + * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected + */ +uint32_t LL_RCC_GetSDMMCClockFreq(uint32_t SDMMCxSource) +{ + uint32_t sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_SDMMC_CLKSOURCE(SDMMCxSource)); + + /* SDMMC1CLK clock frequency */ + switch (LL_RCC_GetSDMMCClockSource(SDMMCxSource)) + { +#if defined(LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1) + case LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SDMMC1 clock source */ + if (LL_RCC_PLLSAI1_IsReady() != 0U) + { + if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() != 0U) + { + sdmmc_frequency = RCC_PLLSAI1_GetFreqDomain_48M(); + } + } + break; +#endif + + case LL_RCC_SDMMC1_CLKSOURCE_PLL: /* PLL clock used as SDMMC1 clock source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U) + { + sdmmc_frequency = RCC_PLL_GetFreqDomain_48M(); + } + } + break; + +#if defined(LL_RCC_SDMMC1_CLKSOURCE_MSI) + case LL_RCC_SDMMC1_CLKSOURCE_MSI: /* MSI clock used as SDMMC1 clock source */ + if (LL_RCC_MSI_IsReady() != 0U) + { + sdmmc_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + } + break; +#endif + +#if defined(RCC_HSI48_SUPPORT) + case LL_RCC_SDMMC1_CLKSOURCE_HSI48: /* HSI48 used as SDMMC1 clock source */ + if (LL_RCC_HSI48_IsReady() != 0U) + { + sdmmc_frequency = HSI48_VALUE; + } + break; +#else + case LL_RCC_SDMMC1_CLKSOURCE_NONE: /* No clock used as SDMMC1 clock source */ +#endif + default: + sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NA; + break; + } + + return sdmmc_frequency; +} +#endif /* SDMMC1 */ + +/** + * @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 (MSI) or PLL is not ready + * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected + */ +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)); + + /* RNGCLK clock frequency */ + switch (LL_RCC_GetRNGClockSource(RNGxSource)) + { +#if defined(RCC_PLLSAI1_SUPPORT) + case LL_RCC_RNG_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as RNG clock source */ + if (LL_RCC_PLLSAI1_IsReady() != 0U) + { + if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() !=0U) + { + rng_frequency = RCC_PLLSAI1_GetFreqDomain_48M(); + } + } + break; +#endif /* RCC_PLLSAI1_SUPPORT */ + + case LL_RCC_RNG_CLKSOURCE_PLL: /* PLL clock used as RNG clock source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U) + { + rng_frequency = RCC_PLL_GetFreqDomain_48M(); + } + } + break; + + case LL_RCC_RNG_CLKSOURCE_MSI: /* MSI clock used as RNG clock source */ + if (LL_RCC_MSI_IsReady() != 0U) + { + rng_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + } + break; + + +#if defined(RCC_HSI48_SUPPORT) + case LL_RCC_RNG_CLKSOURCE_HSI48: /* HSI48 used as RNG clock source */ + if (LL_RCC_HSI48_IsReady() != 0U) + { + rng_frequency = HSI48_VALUE; + } + break; +#else + case LL_RCC_RNG_CLKSOURCE_NONE: /* No clock used as RNG clock source */ +#endif + default: + rng_frequency = LL_RCC_PERIPH_FREQUENCY_NA; + break; + + } + + return rng_frequency; +} + + +#if defined(USB_OTG_FS)||defined(USB) +/** + * @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 (MSI) or PLL is not ready + * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected + */ +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)); + + /* USBCLK clock frequency */ + switch (LL_RCC_GetUSBClockSource(USBxSource)) + { +#if defined(RCC_PLLSAI1_SUPPORT) + case LL_RCC_USB_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as USB clock source */ + if (LL_RCC_PLLSAI1_IsReady() != 0U) + { + if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() != 0U) + { + usb_frequency = RCC_PLLSAI1_GetFreqDomain_48M(); + } + } + break; +#endif /* RCC_PLLSAI1_SUPPORT */ + + case LL_RCC_USB_CLKSOURCE_PLL: /* PLL clock used as USB clock source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U) + { + usb_frequency = RCC_PLL_GetFreqDomain_48M(); + } + } + break; + + case LL_RCC_USB_CLKSOURCE_MSI: /* MSI clock used as USB clock source */ + if (LL_RCC_MSI_IsReady() != 0U) + { + usb_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + } + break; + +#if defined(RCC_HSI48_SUPPORT) + case LL_RCC_USB_CLKSOURCE_HSI48: /* HSI48 used as USB clock source */ + if (LL_RCC_HSI48_IsReady() != 0U) + { + usb_frequency = HSI48_VALUE; + } + break; +#else + case LL_RCC_USB_CLKSOURCE_NONE: /* No clock used as USB clock source */ +#endif + default: + usb_frequency = LL_RCC_PERIPH_FREQUENCY_NA; + break; + } + + return usb_frequency; +} +#endif /* USB_OTG_FS || USB */ + +/** + * @brief Return ADCx clock frequency + * @param ADCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_ADC_CLKSOURCE + * @retval ADC clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready + * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected + */ +uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource) +{ + uint32_t adc_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_ADC_CLKSOURCE(ADCxSource)); + + /* ADCCLK clock frequency */ + switch (LL_RCC_GetADCClockSource(ADCxSource)) + { +#if defined(RCC_PLLSAI1_SUPPORT) + case LL_RCC_ADC_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as ADC clock source */ + if (LL_RCC_PLLSAI1_IsReady() != 0U) + { + if (LL_RCC_PLLSAI1_IsEnabledDomain_ADC() != 0U) + { + adc_frequency = RCC_PLLSAI1_GetFreqDomain_ADC(); + } + } + break; +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) && defined(LL_RCC_ADC_CLKSOURCE_PLLSAI2) + case LL_RCC_ADC_CLKSOURCE_PLLSAI2: /* PLLSAI2 clock used as ADC clock source */ + if (LL_RCC_PLLSAI2_IsReady() != 0U) + { + if (LL_RCC_PLLSAI2_IsEnabledDomain_ADC() != 0U) + { + adc_frequency = RCC_PLLSAI2_GetFreqDomain_ADC(); + } + } + break; +#endif /* RCC_PLLSAI2_SUPPORT && LL_RCC_ADC_CLKSOURCE_PLLSAI2 */ + + case LL_RCC_ADC_CLKSOURCE_SYSCLK: /* SYSCLK clock used as ADC clock source */ + adc_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_ADC_CLKSOURCE_NONE: /* No clock used as ADC clock source */ + default: + adc_frequency = LL_RCC_PERIPH_FREQUENCY_NA; + break; + } + + return adc_frequency; +} + +#if defined(SWPMI1) +/** + * @brief Return SWPMIx clock frequency + * @param SWPMIxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SWPMI1_CLKSOURCE + * @retval SWPMI clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI) is not ready + */ +uint32_t LL_RCC_GetSWPMIClockFreq(uint32_t SWPMIxSource) +{ + uint32_t swpmi_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_SWPMI_CLKSOURCE(SWPMIxSource)); + + /* SWPMI1CLK clock frequency */ + switch (LL_RCC_GetSWPMIClockSource(SWPMIxSource)) + { + case LL_RCC_SWPMI1_CLKSOURCE_HSI: /* SWPMI1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady()) + { + swpmi_frequency = HSI_VALUE; + } + break; + + case LL_RCC_SWPMI1_CLKSOURCE_PCLK1: /* SWPMI1 Clock is PCLK1 */ + swpmi_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + + return swpmi_frequency; +} +#endif /* SWPMI1 */ + +#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 + * @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)); + + /* 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 */ + dfsdm_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + + default: + break; + } + + return dfsdm_frequency; +} + +#if defined(RCC_CCIPR2_DFSDM1SEL) +/** + * @brief Return DFSDMx Audio clock frequency + * @param DFSDMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE + * @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)); + + /* DFSDM1CLK clock frequency */ + switch (LL_RCC_GetDFSDMAudioClockSource(DFSDMxSource)) + { + case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_SAI1: /* SAI1 clock used as DFSDM1 audio clock */ + dfsdm_frequency = LL_RCC_GetSAIClockFreq(LL_RCC_SAI1_CLKSOURCE); + break; + + case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_MSI: /* MSI clock used as DFSDM1 audio clock */ + if (LL_RCC_MSI_IsReady() != 0U) + { + dfsdm_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + } + break; + + case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_HSI: /* HSI clock used as DFSDM1 audio clock */ + default: + if (LL_RCC_HSI_IsReady() != 0U) + { + dfsdm_frequency = HSI_VALUE; + } + break; + } + + return dfsdm_frequency; +} +#endif /* RCC_CCIPR2_DFSDM1SEL */ +#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 PLLSAI2 Osc. */ + if (LL_RCC_PLLSAI2_IsReady() != 0U) + { + if (LL_RCC_PLLSAI2_IsEnabledDomain_DSI() != 0U) + { + dsi_frequency = RCC_PLLSAI2_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_PLLSAI2_IsReady() != 0U) + { + if (LL_RCC_PLLSAI2_IsEnabledDomain_LTDC() != 0U) + { + ltdc_frequency = RCC_PLLSAI2_GetFreqDomain_LTDC(); + } + } + + return ltdc_frequency; +} +#endif /* LTDC */ + +#if defined(OCTOSPI1) +/** + * @brief Return OCTOSPI clock frequency + * @param OCTOSPIxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_OCTOSPI_CLKSOURCE + * @retval OCTOSPI clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator PLLSAI is not ready + */ +uint32_t LL_RCC_GetOCTOSPIClockFreq(uint32_t OCTOSPIxSource) +{ + uint32_t octospi_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_OCTOSPI_CLKSOURCE(OCTOSPIxSource)); + + /* OCTOSPI clock frequency */ + switch (LL_RCC_GetOCTOSPIClockSource(OCTOSPIxSource)) + { + case LL_RCC_OCTOSPI_CLKSOURCE_SYSCLK: /* OCTOSPI clock is SYSCLK */ + octospi_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_OCTOSPI_CLKSOURCE_MSI: /* MSI clock used as OCTOSPI clock */ + if (LL_RCC_MSI_IsReady() != 0U) + { + octospi_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + } + break; + + case LL_RCC_OCTOSPI_CLKSOURCE_PLL: /* PLL clock used as OCTOSPI source */ + if (LL_RCC_PLL_IsReady() != 0U) + { + if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U) + { + octospi_frequency = RCC_PLL_GetFreqDomain_48M(); + } + } + break; + + default: + octospi_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + break; + } + + return octospi_frequency; +} +#endif /* OCTOSPI1 */ + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup RCC_LL_Private_Functions + * @{ + */ + +/** + * @brief Return SYSTEM clock frequency + * @retval SYSTEM clock frequency (in Hz) + */ +static uint32_t RCC_GetSystemClockFreq(void) +{ + uint32_t frequency; + + /* Get SYSCLK source -------------------------------------------------------*/ + switch (LL_RCC_GetSysClkSource()) + { + case LL_RCC_SYS_CLKSOURCE_STATUS_MSI: /* MSI used as system clock source */ + frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + 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(); + break; + + default: + frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + + return frequency; +} + +/** + * @brief Return HCLK clock frequency + * @param SYSCLK_Frequency SYSCLK clock frequency + * @retval HCLK clock frequency (in Hz) + */ +static 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) + */ +static 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) + */ +static 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 + * @retval PLL clock frequency (in Hz) + */ +static uint32_t RCC_PLL_GetFreqDomain_SYS(void) +{ + uint32_t pllinputfreq, pllsource; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + 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 = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + return __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR()); +} + +#if defined(SAI1) +/** + * @brief Return PLL clock frequency used for SAI domain + * @retval PLL clock frequency (in Hz) + */ +static uint32_t RCC_PLL_GetFreqDomain_SAI(void) +{ + uint32_t pllinputfreq, pllsource; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE / PLLM) * PLLN + SAI Domain clock = PLL_VCO / PLLP + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + 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 = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + return __LL_RCC_CALC_PLLCLK_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetP()); +} +#endif /* SAI1 */ + +/** + * @brief Return PLL clock frequency used for 48 MHz domain + * @retval PLL clock frequency (in Hz) + */ +static uint32_t RCC_PLL_GetFreqDomain_48M(void) +{ + uint32_t pllinputfreq, pllsource; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN + 48M Domain clock = PLL_VCO / PLLQ + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + 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 = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + 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) + */ +static uint32_t RCC_PLLSAI2_GetFreqDomain_DSI(void) +{ + uint32_t pllinputfreq, pllsource; + + /* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI2M) * PLLSAI2N */ + /* DSICLK = PLLSAI2_VCO / PLLSAI2R */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + + return __LL_RCC_CALC_PLLSAI2_DSI_FREQ(pllinputfreq, LL_RCC_PLLSAI2_GetDivider(), + LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetR()); +} +#endif /* DSI */ + +#if defined(RCC_PLLSAI1_SUPPORT) +/** + * @brief Return PLLSAI1 clock frequency used for SAI domain + * @retval PLLSAI1 clock frequency (in Hz) + */ +static uint32_t RCC_PLLSAI1_GetFreqDomain_SAI(void) +{ + uint32_t pllinputfreq, pllsource; + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI1M) * PLLSAI1N */ +#else + /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI1N */ +#endif + /* SAI Domain clock = PLLSAI1_VCO / PLLSAI1P */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + return __LL_RCC_CALC_PLLSAI1_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetP()); +} + +/** + * @brief Return PLLSAI1 clock frequency used for 48Mhz domain + * @retval PLLSAI1 clock frequency (in Hz) + */ +static uint32_t RCC_PLLSAI1_GetFreqDomain_48M(void) +{ + uint32_t pllinputfreq, pllsource; + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI1M) * PLLSAI1N */ +#else + /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI1N */ +#endif + /* 48M Domain clock = PLLSAI1_VCO / PLLSAI1Q */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + return __LL_RCC_CALC_PLLSAI1_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetQ()); +} + +/** + * @brief Return PLLSAI1 clock frequency used for ADC domain + * @retval PLLSAI1 clock frequency (in Hz) + */ +static uint32_t RCC_PLLSAI1_GetFreqDomain_ADC(void) +{ + uint32_t pllinputfreq, pllsource; + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI1M) * PLLSAI1N */ +#else + /* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI1N */ +#endif + /* 48M Domain clock = PLLSAI1_VCO / PLLSAI1R */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + return __LL_RCC_CALC_PLLSAI1_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetR()); +} +#endif /* RCC_PLLSAI1_SUPPORT */ + +#if defined(RCC_PLLSAI2_SUPPORT) +/** + * @brief Return PLLSAI2 clock frequency used for SAI domain + * @retval PLLSAI2 clock frequency (in Hz) + */ +static uint32_t RCC_PLLSAI2_GetFreqDomain_SAI(void) +{ + uint32_t pllinputfreq, pllsource; + +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + /* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI2M) * PLLSAI2N */ +#else + /* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI2N */ +#endif + /* SAI Domain clock = PLLSAI2_VCO / PLLSAI2P */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } +#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) + return __LL_RCC_CALC_PLLSAI2_SAI_FREQ(pllinputfreq, LL_RCC_PLLSAI2_GetDivider(), + LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetP()); +#else + return __LL_RCC_CALC_PLLSAI2_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetP()); +#endif +} + +#if defined(LTDC) +/** + * @brief Return PLLSAI2 clock frequency used for LTDC domain + * @retval PLLSAI2 clock frequency (in Hz) + */ +static uint32_t RCC_PLLSAI2_GetFreqDomain_LTDC(void) +{ + uint32_t pllinputfreq, pllsource; + + /* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI2M) * PLLSAI2N */ + /* LTDC Domain clock = (PLLSAI2_VCO / PLLSAI2R) / PLLSAI2DIVR */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + + return __LL_RCC_CALC_PLLSAI2_LTDC_FREQ(pllinputfreq, LL_RCC_PLLSAI2_GetDivider(), + LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetR(), LL_RCC_PLLSAI2_GetDIVR()); +} + +#else + + /** + * @brief Return PLLSAI2 clock frequency used for ADC domain + * @retval PLLSAI2 clock frequency (in Hz) + */ +static uint32_t RCC_PLLSAI2_GetFreqDomain_ADC(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI2N */ + /* 48M Domain clock = PLLSAI2_VCO / PLLSAI2R */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */ + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), + ((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ? + LL_RCC_MSI_GetRange() : + LL_RCC_MSI_GetRangeAfterStandby())); + break; + } + return __LL_RCC_CALC_PLLSAI2_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetR()); +} +#endif /* LTDC */ + +#endif /*RCC_PLLSAI2_SUPPORT*/ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(RCC) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_spi.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_spi.c new file mode 100644 index 0000000..89cc53f --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_spi.c @@ -0,0 +1,295 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_spi.c + * @author MCD Application Team + * @brief SPI 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 "stm32l4xx_ll_spi.h" +#include "stm32l4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) + +/** @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_CRCL | \ + 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_4BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \ + || ((__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 */ + + 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 + * - 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->ClockPolarity | SPI_InitStruct->ClockPhase | + SPI_InitStruct->NSS | SPI_InitStruct->BaudRate | + SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation); + + /*---------------------------- SPIx CR2 Configuration ------------------------ + * Configure SPIx CR2 with parameters: + * - DataWidth: DS[3:0] bits + * - NSS management: SSOE bit + */ + MODIFY_REG(SPIx->CR2, + SPI_CR2_DS | SPI_CR2_SSOE, + SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U)); + + /* Set Rx FIFO to Quarter (1 Byte) in case of 8 Bits mode. No DataPacking by default */ + if (SPI_InitStruct->DataWidth < LL_SPI_DATAWIDTH_9BIT) + { + LL_SPI_SetRxFIFOThreshold(SPIx, LL_SPI_RX_FIFO_TH_QUARTER); + } + + /*---------------------------- 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; + } + + 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; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_tim.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_tim.c new file mode 100644 index 0000000..1ce1776 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_tim.c @@ -0,0 +1,1356 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_tim.c + * @author MCD Application Team + * @brief TIM 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 "stm32l4xx_ll_tim.h" +#include "stm32l4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined (TIM1) || defined (TIM8) || defined (TIM2) || defined (TIM3) || defined (TIM4) || defined (TIM5) || defined (TIM15) || defined (TIM16) || defined (TIM17) || defined (TIM6) || defined (TIM7) + +/** @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) \ + || ((__VALUE__) == LL_TIM_OCMODE_RETRIG_OPM1) \ + || ((__VALUE__) == LL_TIM_OCMODE_RETRIG_OPM2) \ + || ((__VALUE__) == LL_TIM_OCMODE_COMBINED_PWM1) \ + || ((__VALUE__) == LL_TIM_OCMODE_COMBINED_PWM2) \ + || ((__VALUE__) == LL_TIM_OCMODE_ASSYMETRIC_PWM1) \ + || ((__VALUE__) == LL_TIM_OCMODE_ASSYMETRIC_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_BREAK_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N2) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N4) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N8) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV2_N6) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV2_N8) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV4_N6) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV4_N8) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV8_N6) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV8_N8) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N5) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N6) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N8) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N5) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N6) \ + || ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N8)) + +#define IS_LL_TIM_BREAK2_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_DISABLE) \ + || ((__VALUE__) == LL_TIM_BREAK2_ENABLE)) + +#define IS_LL_TIM_BREAK2_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_POLARITY_LOW) \ + || ((__VALUE__) == LL_TIM_BREAK2_POLARITY_HIGH)) + +#define IS_LL_TIM_BREAK2_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N2) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N4) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N8) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV2_N6) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV2_N8) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV4_N6) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV4_N8) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV8_N6) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV8_N8) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N5) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N6) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N8) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N5) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N6) \ + || ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N8)) + +#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 OC5Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct); +static ErrorStatus OC6Config(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(const 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); + } + else if (TIMx == TIM2) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM2); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_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 */ + else if (TIMx == TIM6) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM6); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_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 */ + else if (TIMx == TIM15) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM15); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM15); + } + else if (TIMx == TIM16) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM16); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM16); + } +#if defined(TIM17) + else if (TIMx == TIM17) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM17); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM17); + } +#endif /* TIM17 */ + 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 + * @arg @ref LL_TIM_CHANNEL_CH5 + * @arg @ref LL_TIM_CHANNEL_CH6 + * @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; + case LL_TIM_CHANNEL_CH5: + result = OC5Config(TIMx, TIM_OC_InitStruct); + break; + case LL_TIM_CHANNEL_CH6: + result = OC6Config(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->BreakFilter = LL_TIM_BREAK_FILTER_FDIV1; + TIM_BDTRInitStruct->Break2State = LL_TIM_BREAK2_DISABLE; + TIM_BDTRInitStruct->Break2Polarity = LL_TIM_BREAK2_POLARITY_LOW; + TIM_BDTRInitStruct->Break2Filter = LL_TIM_BREAK2_FILTER_FDIV1; + TIM_BDTRInitStruct->AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE; +} + +/** + * @brief Configure the Break and Dead Time feature of the timer instance. + * @note As the bits BK2P, BK2E, BK2F[3:0], BKF[3:0], AOE, BKP, BKE, OSSI, OSSR + * 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. + * @note Macro IS_TIM_BKIN2_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a second 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); + assert_param(IS_LL_TIM_BREAK_FILTER(TIM_BDTRInitStruct->BreakFilter)); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, TIM_BDTRInitStruct->BreakFilter); + + if (IS_TIM_BKIN2_INSTANCE(TIMx)) + { + assert_param(IS_LL_TIM_BREAK2_STATE(TIM_BDTRInitStruct->Break2State)); + assert_param(IS_LL_TIM_BREAK2_POLARITY(TIM_BDTRInitStruct->Break2Polarity)); + assert_param(IS_LL_TIM_BREAK2_FILTER(TIM_BDTRInitStruct->Break2Filter)); + + /* Set the BREAK2 input related BDTR bit-fields */ + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (TIM_BDTRInitStruct->Break2Filter)); + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, TIM_BDTRInitStruct->Break2State); + MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, TIM_BDTRInitStruct->Break2Polarity); + } + + /* 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 output channel 5. + * @param TIMx Timer Instance + * @param TIM_OCInitStruct pointer to the the TIMx output channel 5 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus OC5Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct) +{ + uint32_t tmpccmr3; + uint32_t tmpccer; + + /* Check the parameters */ + assert_param(IS_TIM_CC5_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 5: Reset the CC5E Bit */ + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC5E); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx CCMR3 register value */ + tmpccmr3 = LL_TIM_ReadReg(TIMx, CCMR3); + + /* Select the Output Compare Mode */ + MODIFY_REG(tmpccmr3, TIM_CCMR3_OC5M, TIM_OCInitStruct->OCMode); + + /* Set the Output Compare Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC5P, TIM_OCInitStruct->OCPolarity << 16U); + + /* Set the Output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC5E, TIM_OCInitStruct->OCState << 16U); + + 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(TIMx->CR2, TIM_CR2_OIS5, TIM_OCInitStruct->OCIdleState << 8U); + + } + + /* Write to TIMx CCMR3 */ + LL_TIM_WriteReg(TIMx, CCMR3, tmpccmr3); + + /* Set the Capture Compare Register value */ + LL_TIM_OC_SetCompareCH5(TIMx, TIM_OCInitStruct->CompareValue); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx output channel 6. + * @param TIMx Timer Instance + * @param TIM_OCInitStruct pointer to the the TIMx output channel 6 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus OC6Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct) +{ + uint32_t tmpccmr3; + uint32_t tmpccer; + + /* Check the parameters */ + assert_param(IS_TIM_CC6_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 5: Reset the CC6E Bit */ + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC6E); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx CCMR3 register value */ + tmpccmr3 = LL_TIM_ReadReg(TIMx, CCMR3); + + /* Select the Output Compare Mode */ + MODIFY_REG(tmpccmr3, TIM_CCMR3_OC6M, TIM_OCInitStruct->OCMode << 8U); + + /* Set the Output Compare Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC6P, TIM_OCInitStruct->OCPolarity << 20U); + + /* Set the Output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC6E, TIM_OCInitStruct->OCState << 20U); + + 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(TIMx->CR2, TIM_CR2_OIS6, TIM_OCInitStruct->OCIdleState << 10U); + } + + /* Write to TIMx CCMR3 */ + LL_TIM_WriteReg(TIMx, CCMR3, tmpccmr3); + + /* Set the Capture Compare Register value */ + LL_TIM_OC_SetCompareCH6(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 || TIM8 || TIM2 || TIM3 || TIM4 || TIM5 || TIM15 || TIM16 || TIM17 || TIM6 || TIM7 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c new file mode 100644 index 0000000..43fd33b --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c @@ -0,0 +1,487 @@ +/** + ****************************************************************************** + * @file stm32l4xx_ll_usart.c + * @author MCD Application Team + * @brief USART 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 "stm32l4xx_ll_usart.h" +#include "stm32l4xx_ll_rcc.h" +#include "stm32l4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +#if defined(USART1) || defined(USART2) || defined(USART3) || defined(UART4) || defined(UART5) + +/** @addtogroup USART_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup USART_LL_Private_Constants + * @{ + */ + +/* Definition of default baudrate value used for USART initialisation */ +#define USART_DEFAULT_BAUDRATE (9600U) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup USART_LL_Private_Macros + * @{ + */ + +#if defined(USART_PRESC_PRESCALER) +#define IS_LL_USART_PRESCALER(__VALUE__) (((__VALUE__) == LL_USART_PRESCALER_DIV1) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV2) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV4) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV6) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV8) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV10) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV12) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV16) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV32) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV64) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV128) \ + || ((__VALUE__) == LL_USART_PRESCALER_DIV256)) + +#endif /* USART_PRESC_PRESCALER */ +/* __BAUDRATE__ The maximum Baud Rate is derived from the maximum clock available + * divided by the smallest oversampling used on the USART (i.e. 8) */ +#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 15000000U) +#else +#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 10000000U) +#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ + +/* __VALUE__ In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. */ +#define IS_LL_USART_BRR_MIN(__VALUE__) ((__VALUE__) >= 16U) + +#define IS_LL_USART_DIRECTION(__VALUE__) (((__VALUE__) == LL_USART_DIRECTION_NONE) \ + || ((__VALUE__) == LL_USART_DIRECTION_RX) \ + || ((__VALUE__) == LL_USART_DIRECTION_TX) \ + || ((__VALUE__) == LL_USART_DIRECTION_TX_RX)) + +#define IS_LL_USART_PARITY(__VALUE__) (((__VALUE__) == LL_USART_PARITY_NONE) \ + || ((__VALUE__) == LL_USART_PARITY_EVEN) \ + || ((__VALUE__) == LL_USART_PARITY_ODD)) + +#define IS_LL_USART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_USART_DATAWIDTH_7B) \ + || ((__VALUE__) == LL_USART_DATAWIDTH_8B) \ + || ((__VALUE__) == LL_USART_DATAWIDTH_9B)) + +#define IS_LL_USART_OVERSAMPLING(__VALUE__) (((__VALUE__) == LL_USART_OVERSAMPLING_16) \ + || ((__VALUE__) == LL_USART_OVERSAMPLING_8)) + +#define IS_LL_USART_LASTBITCLKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_LASTCLKPULSE_NO_OUTPUT) \ + || ((__VALUE__) == LL_USART_LASTCLKPULSE_OUTPUT)) + +#define IS_LL_USART_CLOCKPHASE(__VALUE__) (((__VALUE__) == LL_USART_PHASE_1EDGE) \ + || ((__VALUE__) == LL_USART_PHASE_2EDGE)) + +#define IS_LL_USART_CLOCKPOLARITY(__VALUE__) (((__VALUE__) == LL_USART_POLARITY_LOW) \ + || ((__VALUE__) == LL_USART_POLARITY_HIGH)) + +#define IS_LL_USART_CLOCKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_CLOCK_DISABLE) \ + || ((__VALUE__) == LL_USART_CLOCK_ENABLE)) + +#define IS_LL_USART_STOPBITS(__VALUE__) (((__VALUE__) == LL_USART_STOPBITS_0_5) \ + || ((__VALUE__) == LL_USART_STOPBITS_1) \ + || ((__VALUE__) == LL_USART_STOPBITS_1_5) \ + || ((__VALUE__) == LL_USART_STOPBITS_2)) + +#define IS_LL_USART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_USART_HWCONTROL_NONE) \ + || ((__VALUE__) == LL_USART_HWCONTROL_RTS) \ + || ((__VALUE__) == LL_USART_HWCONTROL_CTS) \ + || ((__VALUE__) == LL_USART_HWCONTROL_RTS_CTS)) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup USART_LL_Exported_Functions + * @{ + */ + +/** @addtogroup USART_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize USART registers (Registers restored to their default values). + * @param USARTx USART Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers are de-initialized + * - ERROR: USART registers are not de-initialized + */ +ErrorStatus LL_USART_DeInit(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(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 */ + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Initialize USART registers according to the specified + * parameters in USART_InitStruct. + * @note As some bits in USART configuration registers can only be written when + * the USART is disabled (USART_CR1_UE bit =0), USART Peripheral should be in disabled state prior calling + * this function. Otherwise, ERROR result will be returned. + * @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0). + * @param USARTx USART Instance + * @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure + * that contains the configuration information for the specified USART peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers are initialized according to USART_InitStruct content + * - ERROR: Problem occurred during USART Registers initialization + */ +ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, const LL_USART_InitTypeDef *USART_InitStruct) +{ + ErrorStatus status = ERROR; + uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); +#if defined(USART_PRESC_PRESCALER) + assert_param(IS_LL_USART_PRESCALER(USART_InitStruct->PrescalerValue)); +#endif /* USART_PRESC_PRESCALER */ + assert_param(IS_LL_USART_BAUDRATE(USART_InitStruct->BaudRate)); + assert_param(IS_LL_USART_DATAWIDTH(USART_InitStruct->DataWidth)); + assert_param(IS_LL_USART_STOPBITS(USART_InitStruct->StopBits)); + assert_param(IS_LL_USART_PARITY(USART_InitStruct->Parity)); + assert_param(IS_LL_USART_DIRECTION(USART_InitStruct->TransferDirection)); + assert_param(IS_LL_USART_HWCONTROL(USART_InitStruct->HardwareFlowControl)); + assert_param(IS_LL_USART_OVERSAMPLING(USART_InitStruct->OverSampling)); + + /* USART needs to be in disabled state, in order to be able to configure some bits in + CRx registers */ + if (LL_USART_IsEnabled(USARTx) == 0U) + { + /*---------------------------- USART CR1 Configuration --------------------- + * Configure USARTx CR1 (USART Word Length, Parity, Mode and Oversampling bits) with parameters: + * - DataWidth: USART_CR1_M bits according to USART_InitStruct->DataWidth value + * - Parity: USART_CR1_PCE, USART_CR1_PS bits according to USART_InitStruct->Parity value + * - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to USART_InitStruct->TransferDirection value + * - Oversampling: USART_CR1_OVER8 bit according to USART_InitStruct->OverSampling value. + */ + MODIFY_REG(USARTx->CR1, + (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8), + (USART_InitStruct->DataWidth | USART_InitStruct->Parity | + USART_InitStruct->TransferDirection | USART_InitStruct->OverSampling)); + + /*---------------------------- USART CR2 Configuration --------------------- + * Configure USARTx CR2 (Stop bits) with parameters: + * - Stop Bits: USART_CR2_STOP bits according to USART_InitStruct->StopBits value. + * - CLKEN, CPOL, CPHA and LBCL bits are to be configured using LL_USART_ClockInit(). + */ + LL_USART_SetStopBitsLength(USARTx, USART_InitStruct->StopBits); + + /*---------------------------- USART CR3 Configuration --------------------- + * Configure USARTx CR3 (Hardware Flow Control) with parameters: + * - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to + * USART_InitStruct->HardwareFlowControl value. + */ + LL_USART_SetHWFlowCtrl(USARTx, USART_InitStruct->HardwareFlowControl); + + /*---------------------------- USART BRR Configuration --------------------- + * Retrieve Clock frequency used for USART Peripheral + */ + if (USARTx == USART1) + { + periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE); + } + else if (USARTx == USART2) + { + periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART2_CLKSOURCE); + } +#if defined(USART3) + else if (USARTx == USART3) + { + periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART3_CLKSOURCE); + } +#endif /* USART3 */ +#if defined(UART4) + else if (USARTx == UART4) + { + periphclk = LL_RCC_GetUARTClockFreq(LL_RCC_UART4_CLKSOURCE); + } +#endif /* UART4 */ +#if defined(UART5) + else if (USARTx == UART5) + { + periphclk = LL_RCC_GetUARTClockFreq(LL_RCC_UART5_CLKSOURCE); + } +#endif /* UART5 */ + else + { + /* Nothing to do, as error code is already assigned to ERROR value */ + } + + /* Configure the USART Baud Rate : + #if defined(USART_PRESC_PRESCALER) + - prescaler value is required + #endif + - 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, +#if defined(USART_PRESC_PRESCALER) + USART_InitStruct->PrescalerValue, +#endif /* USART_PRESC_PRESCALER */ + USART_InitStruct->OverSampling, + USART_InitStruct->BaudRate); + + /* Check BRR is greater than or equal to 16d */ + assert_param(IS_LL_USART_BRR_MIN(USARTx->BRR)); + } +#if defined(USART_PRESC_PRESCALER) + + /*---------------------------- USART PRESC Configuration ----------------------- + * Configure USARTx PRESC (Prescaler) with parameters: + * - PrescalerValue: USART_PRESC_PRESCALER bits according to USART_InitStruct->PrescalerValue value. + */ + LL_USART_SetPrescaler(USARTx, USART_InitStruct->PrescalerValue); +#endif /* USART_PRESC_PRESCALER */ + } + /* 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 */ +#if defined(USART_PRESC_PRESCALER) + USART_InitStruct->PrescalerValue = LL_USART_PRESCALER_DIV1; +#endif /* USART_PRESC_PRESCALER */ + USART_InitStruct->BaudRate = USART_DEFAULT_BAUDRATE; + USART_InitStruct->DataWidth = LL_USART_DATAWIDTH_8B; + USART_InitStruct->StopBits = LL_USART_STOPBITS_1; + USART_InitStruct->Parity = LL_USART_PARITY_NONE ; + USART_InitStruct->TransferDirection = LL_USART_DIRECTION_TX_RX; + USART_InitStruct->HardwareFlowControl = LL_USART_HWCONTROL_NONE; + USART_InitStruct->OverSampling = LL_USART_OVERSAMPLING_16; +} + +/** + * @brief Initialize USART Clock related settings according to the + * specified parameters in the USART_ClockInitStruct. + * @note As some bits in USART configuration registers can only be written when + * the USART is disabled (USART_CR1_UE bit =0), USART Peripheral should be in disabled state prior calling + * this function. Otherwise, ERROR result will be returned. + * @param USARTx USART Instance + * @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure + * that contains the Clock configuration information for the specified USART peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers related to Clock settings are initialized according + * to USART_ClockInitStruct content + * - ERROR: Problem occurred during USART Registers initialization + */ +ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, 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) + { +#if defined(USART_CR2_SLVEN) + /* 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: + * - Clock Output: USART_CR2_CLKEN bit according to USART_ClockInitStruct->ClockOutput value + * - 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_ClockInitStruct->ClockOutput | USART_ClockInitStruct->ClockPolarity | + USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse); +#else + /* If USART Clock signal is disabled */ + if (USART_ClockInitStruct->ClockOutput == LL_USART_CLOCK_DISABLE) + { + /* Deactivate Clock signal delivery : + * - Disable Clock Output: USART_CR2_CLKEN cleared + */ + LL_USART_DisableSCLKOutput(USARTx); + } + else + { + /* Ensure USART instance is USART capable */ + assert_param(IS_USART_INSTANCE(USARTx)); + + /* Check clock related parameters */ + assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity)); + assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase)); + assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse)); + + /*---------------------------- USART CR2 Configuration ----------------------- + * Configure USARTx CR2 (Clock signal related bits) with parameters: + * - Enable Clock Output: USART_CR2_CLKEN set + * - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value + * - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value + * - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value. + */ + MODIFY_REG(USARTx->CR2, + USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL, + USART_CR2_CLKEN | USART_ClockInitStruct->ClockPolarity | + USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse); + } +#endif /* USART_CR2_SLVEN */ + } + /* 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 || UART4 || UART5 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + + diff --git a/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c new file mode 100644 index 0000000..5375be8 --- /dev/null +++ b/Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c @@ -0,0 +1,913 @@ +/** + ****************************************************************************** + * @file stm32l4xx_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 "stm32l4xx_ll_utils.h" +#include "stm32l4xx_ll_rcc.h" +#include "stm32l4xx_ll_system.h" +#include "stm32l4xx_ll_pwr.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +/** @addtogroup UTILS_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup UTILS_LL_Private_Constants + * @{ + */ +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define UTILS_MAX_FREQUENCY_SCALE1 120000000U /*!< Maximum frequency for system clock at power scale1, in Hz */ +#define UTILS_MAX_FREQUENCY_SCALE2 26000000U /*!< Maximum frequency for system clock at power scale2, in Hz */ +#else +#define UTILS_MAX_FREQUENCY_SCALE1 80000000U /*!< Maximum frequency for system clock at power scale1, in Hz */ +#define UTILS_MAX_FREQUENCY_SCALE2 26000000U /*!< Maximum frequency for system clock at power scale2, in Hz */ +#endif + +/* Defines used for PLL range */ +#define UTILS_PLLVCO_INPUT_MIN 4000000U /*!< Frequency min for PLLVCO input, in Hz */ +#define UTILS_PLLVCO_INPUT_MAX 16000000U /*!< Frequency max for PLLVCO input, in Hz */ +#define UTILS_PLLVCO_OUTPUT_MIN 64000000U /*!< Frequency min for PLLVCO output, in Hz */ +#define UTILS_PLLVCO_OUTPUT_MAX 344000000U /*!< 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 48000000U /*!< Frequency max for HSE frequency, in Hz */ + +/* Defines used for FLASH latency according to HCLK Frequency */ +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) +#define UTILS_SCALE1_LATENCY1_FREQ 20000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */ +#define UTILS_SCALE1_LATENCY2_FREQ 40000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */ +#define UTILS_SCALE1_LATENCY3_FREQ 60000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */ +#define UTILS_SCALE1_LATENCY4_FREQ 80000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */ +#define UTILS_SCALE1_LATENCY5_FREQ 100000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */ +#define UTILS_SCALE2_LATENCY1_FREQ 8000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */ +#define UTILS_SCALE2_LATENCY2_FREQ 16000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */ +#else +#define UTILS_SCALE1_LATENCY1_FREQ 16000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */ +#define UTILS_SCALE1_LATENCY2_FREQ 32000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */ +#define UTILS_SCALE1_LATENCY3_FREQ 48000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */ +#define UTILS_SCALE1_LATENCY4_FREQ 64000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */ +#define UTILS_SCALE2_LATENCY1_FREQ 6000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */ +#define UTILS_SCALE2_LATENCY2_FREQ 12000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */ +#define UTILS_SCALE2_LATENCY3_FREQ 18000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 2 */ +#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_1) \ + || ((__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)) + +#define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U)) + +#define IS_LL_UTILS_PLLR_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLR_DIV_2) \ + || ((__VALUE__) == LL_RCC_PLLR_DIV_4) \ + || ((__VALUE__) == LL_RCC_PLLR_DIV_6) \ + || ((__VALUE__) == LL_RCC_PLLR_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)) + +#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)) + +#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 */ + uint32_t tmpDelay = Delay; + + /* Add this code to indicate that local variable is not used */ + ((void)tmp); + + /* Add a period to guaranty minimum wait */ + if(tmpDelay < LL_MAX_DELAY) + { + tmpDelay++; + } + + while (tmpDelay != 0U) + { + if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U) + { + tmpDelay--; + } + } +} + +/** + * @} + */ + +/** @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 + 120000000 Hz for STM32L4Rx/STM32L4Sx devices and 80000000 Hz for others. + @endverbatim + @internal + Depending on the device voltage range, the maximum frequency should be + adapted accordingly: + + (++) Table 1. HCLK clock frequency for STM32L4+ Series devices + (++) +--------------------------------------------------------+ + (++) | Latency | HCLK clock frequency (MHz) | + (++) | |--------------------------------------| + (++) | | voltage range 1 | voltage range 2 | + (++) | | 1.2 V | 1.0 V | + (++) |-----------------|-------------------|------------------| + (++) |0WS(1 CPU cycles)| 0 < HCLK <= 20 | 0 < HCLK <= 8 | + (++) |-----------------|-------------------|------------------| + (++) |1WS(2 CPU cycles)| 20 < HCLK <= 40 | 8 < HCLK <= 16 | + (++) |-----------------|-------------------|------------------| + (++) |2WS(3 CPU cycles)| 40 < HCLK <= 60 | 16 < HCLK <= 26 | + (++) |-----------------|-------------------|------------------| + (++) |3WS(4 CPU cycles)| 60 < HCLK <= 80 | 16 < HCLK <= 26 | + (++) |-----------------|-------------------|------------------| + (++) |4WS(5 CPU cycles)| 80 < HCLK <= 100 | 16 < HCLK <= 26 | + (++) |-----------------|-------------------|------------------| + (++) |5WS(6 CPU cycles)| 100 < HCLK <= 120 | 16 < HCLK <= 26 | + (++) +--------------------------------------------------------+ + + (++) Table 2. HCLK clock frequency for STM32L4 Series devices + (++) +-------------------------------------------------------+ + (++) | Latency | HCLK clock frequency (MHz) | + (++) | |-------------------------------------| + (++) | | voltage range 1 | voltage range 2 | + (++) | | 1.2 V | 1.0 V | + (++) |-----------------|------------------|------------------| + (++) |0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 | + (++) |-----------------|------------------|------------------| + (++) |1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 | + (++) |-----------------|------------------|------------------| + (++) |2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 | + (++) |-----------------|------------------|------------------| + (++) |3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 | + (++) |-----------------|------------------|------------------| + (++) |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 | + (++) +-------------------------------------------------------+ + + @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. + * @param HCLKFrequency HCLK frequency + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Latency has been modified + * - ERROR: Latency cannot be modified + */ +ErrorStatus LL_SetFlashLatency(uint32_t HCLKFrequency) +{ + ErrorStatus status = SUCCESS; + + uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */ + + /* Frequency cannot be equal to 0 or greater than max clock */ + if ((HCLKFrequency == 0U) || (HCLKFrequency > UTILS_MAX_FREQUENCY_SCALE1)) + { + status = ERROR; + } + else + { + if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) + { +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + if(HCLKFrequency > UTILS_SCALE1_LATENCY5_FREQ) + { + /* 100 < HCLK <= 120 => 5WS (6 CPU cycles) */ + latency = LL_FLASH_LATENCY_5; + } + else if(HCLKFrequency > UTILS_SCALE1_LATENCY4_FREQ) + { + /* 80 < HCLK <= 100 => 4WS (5 CPU cycles) */ + latency = LL_FLASH_LATENCY_4; + } + else if(HCLKFrequency > UTILS_SCALE1_LATENCY3_FREQ) + { + /* 60 < HCLK <= 80 => 3WS (4 CPU cycles) */ + latency = LL_FLASH_LATENCY_3; + } + else if(HCLKFrequency > UTILS_SCALE1_LATENCY2_FREQ) + { + /* 40 < HCLK <= 20 => 2WS (3 CPU cycles) */ + latency = LL_FLASH_LATENCY_2; + } + else + { + if(HCLKFrequency > UTILS_SCALE1_LATENCY1_FREQ) + { + /* 20 < HCLK <= 40 => 1WS (2 CPU cycles) */ + latency = LL_FLASH_LATENCY_1; + } + /* else HCLKFrequency <= 10MHz default LL_FLASH_LATENCY_0 0WS */ + } +#else + if(HCLKFrequency > UTILS_SCALE1_LATENCY4_FREQ) + { + /* 64 < HCLK <= 80 => 4WS (5 CPU cycles) */ + latency = LL_FLASH_LATENCY_4; + } + else if(HCLKFrequency > UTILS_SCALE1_LATENCY3_FREQ) + { + /* 48 < HCLK <= 64 => 3WS (4 CPU cycles) */ + latency = LL_FLASH_LATENCY_3; + } + else if(HCLKFrequency > UTILS_SCALE1_LATENCY2_FREQ) + { + /* 32 < HCLK <= 48 => 2WS (3 CPU cycles) */ + latency = LL_FLASH_LATENCY_2; + } + else + { + if(HCLKFrequency > UTILS_SCALE1_LATENCY1_FREQ) + { + /* 16 < HCLK <= 32 => 1WS (2 CPU cycles) */ + latency = LL_FLASH_LATENCY_1; + } + /* else HCLKFrequency <= 16MHz default LL_FLASH_LATENCY_0 0WS */ + } +#endif + } + else /* SCALE2 */ + { +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + if(HCLKFrequency > UTILS_MAX_FREQUENCY_SCALE2) + { + /* Unexpected HCLK > 26 */ + status = ERROR; + } + else if(HCLKFrequency > UTILS_SCALE2_LATENCY2_FREQ) + { + /* 16 < HCLK <= 26 => 2WS (3 CPU cycles) */ + latency = LL_FLASH_LATENCY_2; + } + else + { + if(HCLKFrequency > UTILS_SCALE2_LATENCY1_FREQ) + { + /* 8 < HCLK <= 16 => 1WS (2 CPU cycles) */ + latency = LL_FLASH_LATENCY_1; + } + /* else HCLKFrequency <= 8MHz default LL_FLASH_LATENCY_0 0WS */ + } +#else + if(HCLKFrequency > UTILS_MAX_FREQUENCY_SCALE2) + { + /* Unexpected HCLK > 26 */ + status = ERROR; + } + else if(HCLKFrequency > UTILS_SCALE2_LATENCY3_FREQ) + { + /* 18 < HCLK <= 26 => 3WS (4 CPU cycles) */ + latency = LL_FLASH_LATENCY_3; + } + else if(HCLKFrequency > UTILS_SCALE2_LATENCY2_FREQ) + { + /* 12 < HCLK <= 18 => 2WS (3 CPU cycles) */ + latency = LL_FLASH_LATENCY_2; + } + else + { + if(HCLKFrequency > UTILS_SCALE2_LATENCY1_FREQ) + { + /* 6 < HCLK <= 12 => 1WS (2 CPU cycles) */ + latency = LL_FLASH_LATENCY_1; + } + /* else HCLKFrequency <= 6MHz default LL_FLASH_LATENCY_0 0WS */ + } +#endif + } + + 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 */ + if(LL_FLASH_GetLatency() != latency) + { + status = ERROR; + } + } + return status; +} + +/** + * @brief This function configures system clock with MSI as clock source of the PLL + * @note The application needs to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled. + * @note Function is based on the following formula: + * - PLL output frequency = (((MSI frequency / PLLM) * PLLN) / PLLR) + * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = MSI frequency / PLLM) + * - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN) + * - PLLR: ensure that max frequency at 120000000 Hz is reached (PLLVCO_output / PLLR) + * @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_MSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, + LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) +{ + ErrorStatus status = SUCCESS; + uint32_t pllfreq, msi_range; +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t hpre = 0U; /* Set default value */ +#endif + + /* Check if one of the PLL is enabled */ + if(UTILS_PLL_IsBusy() == SUCCESS) + { + /* Get the current MSI range */ + if(LL_RCC_MSI_IsEnabledRangeSelect() != 0U) + { + msi_range = LL_RCC_MSI_GetRange(); + switch (msi_range) + { + case LL_RCC_MSIRANGE_0: /* MSI = 100 KHz */ + case LL_RCC_MSIRANGE_1: /* MSI = 200 KHz */ + case LL_RCC_MSIRANGE_2: /* MSI = 400 KHz */ + case LL_RCC_MSIRANGE_3: /* MSI = 800 KHz */ + case LL_RCC_MSIRANGE_4: /* MSI = 1 MHz */ + case LL_RCC_MSIRANGE_5: /* MSI = 2 MHz */ + /* PLLVCO input frequency is not in the range from 4 to 16 MHz*/ + status = ERROR; + break; + + case LL_RCC_MSIRANGE_6: /* MSI = 4 MHz */ + case LL_RCC_MSIRANGE_7: /* MSI = 8 MHz */ + case LL_RCC_MSIRANGE_8: /* MSI = 16 MHz */ + case LL_RCC_MSIRANGE_9: /* MSI = 24 MHz */ + case LL_RCC_MSIRANGE_10: /* MSI = 32 MHz */ + case LL_RCC_MSIRANGE_11: /* MSI = 48 MHz */ + default: + break; + } + } + else + { + msi_range = LL_RCC_MSI_GetRangeAfterStandby(); + switch (msi_range) + { + case LL_RCC_MSISRANGE_4: /* MSI = 1 MHz */ + case LL_RCC_MSISRANGE_5: /* MSI = 2 MHz */ + /* PLLVCO input frequency is not in the range from 4 to 16 MHz*/ + status = ERROR; + break; + + case LL_RCC_MSISRANGE_7: /* MSI = 8 MHz */ + case LL_RCC_MSISRANGE_6: /* MSI = 4 MHz */ + default: + break; + } + } + + /* Main PLL configuration and activation */ + if(status != ERROR) + { + /* Calculate the new PLL output frequency */ + pllfreq = UTILS_GetPLLOutputFrequency(__LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), msi_range), + UTILS_PLLInitStruct); + + /* Enable MSI if not enabled */ + if(LL_RCC_MSI_IsReady() != 1U) + { + LL_RCC_MSI_Enable(); + while ((LL_RCC_MSI_IsReady() != 1U)) + { + /* Wait for MSI ready */ + } + } + + /* Configure PLL */ + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN, + UTILS_PLLInitStruct->PLLR); + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Prevent undershoot at highest frequency by applying intermediate AHB prescaler 2 */ + if(pllfreq > 80000000U) + { + if(UTILS_ClkInitStruct->AHBCLKDivider == LL_RCC_SYSCLK_DIV_1) + { + UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_2; + hpre = LL_RCC_SYSCLK_DIV_2; + } + } +#endif + /* Enable PLL and switch system clock to PLL */ + status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Apply definitive AHB prescaler value if necessary */ + if((status == SUCCESS) && (hpre != LL_RCC_SYSCLK_DIV_1)) + { + /* Set FLASH latency to highest latency */ + status = LL_SetFlashLatency(pllfreq); + if(status == SUCCESS) + { + UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_1; + LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider); + LL_SetSystemCoreClock(pllfreq); + } + } +#endif + } + } + else + { + /* Current PLL configuration cannot be modified */ + status = ERROR; + } + + 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, PLLSAI1 and/or PLLSAI2 are disabled. + * @note Function is based on the following formula: + * - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLR) + * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSI frequency / PLLM) + * - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN) + * - PLLR: ensure that max frequency at 120000000 Hz is reach (PLLVCO_output / PLLR) + * @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; + uint32_t pllfreq; +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t hpre = LL_RCC_SYSCLK_DIV_1; /* Set default value */ +#endif + + /* 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->PLLR); + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Prevent undershoot at highest frequency by applying intermediate AHB prescaler 2 */ + if(pllfreq > 80000000U) + { + if(UTILS_ClkInitStruct->AHBCLKDivider == LL_RCC_SYSCLK_DIV_1) + { + UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_2; + hpre = LL_RCC_SYSCLK_DIV_2; + } + } +#endif + /* Enable PLL and switch system clock to PLL */ + status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Apply definitive AHB prescaler value if necessary */ + if((status == SUCCESS) && (hpre != LL_RCC_SYSCLK_DIV_1)) + { + /* Set FLASH latency to highest latency */ + status = LL_SetFlashLatency(pllfreq); + if(status == SUCCESS) + { + UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_1; + LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider); + LL_SetSystemCoreClock(pllfreq); + } + } +#endif + } + 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, PLLSAI1 and/or PLLSAI2 are disabled. + * @note Function is based on the following formula: + * - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLR) + * - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSE frequency / PLLM) + * - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN) + * - PLLR: ensure that max frequency at 120000000 Hz is reached (PLLVCO_output / PLLR) + * @param HSEFrequency Value between Min_Data = 4000000 and Max_Data = 48000000 + * @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; + uint32_t pllfreq; +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + uint32_t hpre = 0U; /* Set default value */ +#endif + + /* 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->PLLR); + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Prevent undershoot at highest frequency by applying intermediate AHB prescaler 2 */ + if(pllfreq > 80000000U) + { + if(UTILS_ClkInitStruct->AHBCLKDivider == LL_RCC_SYSCLK_DIV_1) + { + UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_2; + hpre = LL_RCC_SYSCLK_DIV_2; + } + } +#endif + /* Enable PLL and switch system clock to PLL */ + status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); + +#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \ + defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx) + /* Apply definitive AHB prescaler value if necessary */ + if((status == SUCCESS) && (hpre != LL_RCC_SYSCLK_DIV_1)) + { + /* Set FLASH latency to highest latency */ + status = LL_SetFlashLatency(pllfreq); + if(status == SUCCESS) + { + UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_1; + LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider); + LL_SetSystemCoreClock(pllfreq); + } + } +#endif + } + 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; + + /* 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_PLLR_VALUE(UTILS_PLLInitStruct->PLLR)); + + /* Check different PLL parameters according to RM */ + /* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz. */ + pllfreq = PLL_InputFrequency / (((UTILS_PLLInitStruct->PLLM >> RCC_PLLCFGR_PLLM_Pos) + 1U)); + assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq)); + + /* - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz.*/ + pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN & (RCC_PLLCFGR_PLLN >> RCC_PLLCFGR_PLLN_Pos)); + assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq)); + + /* - PLLR: ensure that max frequency at 120000000 Hz is reached */ + pllfreq = pllfreq / (((UTILS_PLLInitStruct->PLLR >> RCC_PLLCFGR_PLLR_Pos) + 1U) * 2U); + 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_PLLSAI1_SUPPORT) + /* Check if PLLSAI1 is busy*/ + if(LL_RCC_PLLSAI1_IsReady() != 0U) + { + /* PLLSAI1 configuration cannot be modified */ + status = ERROR; + } +#endif /*RCC_PLLSAI1_SUPPORT*/ +#if defined(RCC_PLLSAI2_SUPPORT) + + /* Check if PLLSAI2 is busy*/ + if(LL_RCC_PLLSAI2_IsReady() != 0U) + { + /* PLLSAI2 configuration cannot be modified */ + status = ERROR; + } +#endif /*RCC_PLLSAI2_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; + + 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(); + LL_RCC_PLL_EnableDomain_SYS(); + 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/MDK-ARM/.gitignore b/MDK-ARM/.gitignore new file mode 100644 index 0000000..c2f4ce9 --- /dev/null +++ b/MDK-ARM/.gitignore @@ -0,0 +1,15 @@ +# dot files +/.vscode/launch.json +/.settings +/.eide/log +/.eide.usr.ctx.json + +# project out +/build +/bin +/obj +/out + +# eide template +*.ept +*.eide-template diff --git a/MDK-ARM/EventRecorderStub.scvd b/MDK-ARM/EventRecorderStub.scvd new file mode 100644 index 0000000..2956b29 --- /dev/null +++ b/MDK-ARM/EventRecorderStub.scvd @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/MDK-ARM/JLinkSettings.ini b/MDK-ARM/JLinkSettings.ini new file mode 100644 index 0000000..e635dbf --- /dev/null +++ b/MDK-ARM/JLinkSettings.ini @@ -0,0 +1,44 @@ +[BREAKPOINTS] +ForceImpTypeAny = 0 +ShowInfoWin = 1 +EnableFlashBP = 2 +BPDuringExecution = 0 +[CFI] +CFISize = 0x00 +CFIAddr = 0x00 +[CPU] +MonModeVTableAddr = 0xFFFFFFFF +MonModeDebug = 0 +MaxNumAPs = 0 +LowPowerHandlingMode = 0 +OverrideMemMap = 0 +AllowSimulation = 1 +ScriptFile="" +[FLASH] +RMWThreshold = 0x400 +Loaders="" +EraseType = 0x00 +CacheExcludeSize = 0x00 +CacheExcludeAddr = 0x00 +MinNumBytesFlashDL = 0 +SkipProgOnCRCMatch = 1 +VerifyDownload = 1 +AllowCaching = 1 +EnableFlashDL = 2 +Override = 0 +Device="ARM7" +[GENERAL] +WorkRAMSize = 0x00 +WorkRAMAddr = 0x00 +RAMUsageLimit = 0x00 +[SWO] +SWOLogFile="" +[MEM] +RdOverrideOrMask = 0x00 +RdOverrideAndMask = 0xFFFFFFFF +RdOverrideAddr = 0xFFFFFFFF +WrOverrideOrMask = 0x00 +WrOverrideAndMask = 0xFFFFFFFF +WrOverrideAddr = 0xFFFFFFFF +[RAM] +VerifyDownload = 0x00 diff --git a/MDK-ARM/RTE/_bootload/RTE_Components.h b/MDK-ARM/RTE/_bootload/RTE_Components.h new file mode 100644 index 0000000..a62e5cb --- /dev/null +++ b/MDK-ARM/RTE/_bootload/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'bootload' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_bootload1/RTE_Components.h b/MDK-ARM/RTE/_bootload1/RTE_Components.h new file mode 100644 index 0000000..6106829 --- /dev/null +++ b/MDK-ARM/RTE/_bootload1/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'bootload1' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_common/RTE_Components.h b/MDK-ARM/RTE/_common/RTE_Components.h new file mode 100644 index 0000000..952d21c --- /dev/null +++ b/MDK-ARM/RTE/_common/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v4' + * Target: 'common' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-epm/RTE_Components.h b/MDK-ARM/RTE/_controller-epm/RTE_Components.h new file mode 100644 index 0000000..69b9a4e --- /dev/null +++ b/MDK-ARM/RTE/_controller-epm/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-epm' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v2.4/RTE_Components.h b/MDK-ARM/RTE/_controller-v2.4/RTE_Components.h new file mode 100644 index 0000000..f154d1f --- /dev/null +++ b/MDK-ARM/RTE/_controller-v2.4/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v2.4' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v2.5/RTE_Components.h b/MDK-ARM/RTE/_controller-v2.5/RTE_Components.h new file mode 100644 index 0000000..91ddf0d --- /dev/null +++ b/MDK-ARM/RTE/_controller-v2.5/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v2.5' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v2/RTE_Components.h b/MDK-ARM/RTE/_controller-v2/RTE_Components.h new file mode 100644 index 0000000..391636b --- /dev/null +++ b/MDK-ARM/RTE/_controller-v2/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v2' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v24/RTE_Components.h b/MDK-ARM/RTE/_controller-v24/RTE_Components.h new file mode 100644 index 0000000..64d95c4 --- /dev/null +++ b/MDK-ARM/RTE/_controller-v24/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v24' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v25/RTE_Components.h b/MDK-ARM/RTE/_controller-v25/RTE_Components.h new file mode 100644 index 0000000..74e75d9 --- /dev/null +++ b/MDK-ARM/RTE/_controller-v25/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v25' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v4/RTE_Components.h b/MDK-ARM/RTE/_controller-v4/RTE_Components.h new file mode 100644 index 0000000..a5596d2 --- /dev/null +++ b/MDK-ARM/RTE/_controller-v4/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v4' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_controller-v5/RTE_Components.h b/MDK-ARM/RTE/_controller-v5/RTE_Components.h new file mode 100644 index 0000000..0f39701 --- /dev/null +++ b/MDK-ARM/RTE/_controller-v5/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'controller-v5' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_gui/RTE_Components.h b/MDK-ARM/RTE/_gui/RTE_Components.h new file mode 100644 index 0000000..61dafe6 --- /dev/null +++ b/MDK-ARM/RTE/_gui/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'gui' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_hart/RTE_Components.h b/MDK-ARM/RTE/_hart/RTE_Components.h new file mode 100644 index 0000000..83dac62 --- /dev/null +++ b/MDK-ARM/RTE/_hart/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v4' + * Target: 'hart' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/RTE/_update/RTE_Components.h b/MDK-ARM/RTE/_update/RTE_Components.h new file mode 100644 index 0000000..e9ed15d --- /dev/null +++ b/MDK-ARM/RTE/_update/RTE_Components.h @@ -0,0 +1,21 @@ + +/* + * Auto generated Run-Time-Environment Configuration File + * *** Do not modify ! *** + * + * Project: 'controller-v2' + * Target: 'update' + */ + +#ifndef RTE_COMPONENTS_H +#define RTE_COMPONENTS_H + + +/* + * Define the Device Header File: + */ +#define CMSIS_device_header "stm32l4xx.h" + + + +#endif /* RTE_COMPONENTS_H */ diff --git a/MDK-ARM/conf.cppcheck b/MDK-ARM/conf.cppcheck new file mode 100644 index 0000000..ad1c69c --- /dev/null +++ b/MDK-ARM/conf.cppcheck @@ -0,0 +1,30 @@ + + + + ${cppcheck_build_folder} + ${platform} + false + true + true + 2 + 100 + + + ${include_list} + + + + ${macro_list} + + + + + + + ${source_list} + + + + ${lib_list} + + diff --git a/MDK-ARM/controller-v2.CTmp b/MDK-ARM/controller-v2.CTmp new file mode 100644 index 0000000..e69de29 diff --git a/MDK-ARM/controller-v2.uvoptx b/MDK-ARM/controller-v2.uvoptx new file mode 100644 index 0000000..feb3eed --- /dev/null +++ b/MDK-ARM/controller-v2.uvoptx @@ -0,0 +1,1502 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj; *.o + *.lib + *.txt; *.h; *.inc; *.md + *.plm + *.cpp; *.cc; *.cxx + 0 + + + + 0 + 0 + + + + controller-v2 + 0x4 + ARM-ADS + + 8000000 + + 1 + 1 + 0 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 18 + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 6 + + + + + + + + + + + STLink\ST-LINKIII-KEIL_SWO.dll + + + + 0 + JL2CM3 + -U601012352 -O78 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC8000 -FN1 -FF0STM32L4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32L476VGTx$CMSIS\Flash\STM32L4xx_1024.FLM) + + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + ST-LINKIII-KEIL_SWO + -U-O206 -O206 -SF10000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP (ARM Core") -D00(2BA01477) -L00(0) -TO131090 -TC10000000 -TT10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC8000 -FN1 -FF0STM32L4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32L476VGTx$CMSIS\Flash\STM32L4xx_1024.FLM) + + + 0 + DLGUARM + (105=-1,-1,-1,-1,0) + + + 0 + UL2CM3 + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0STM32L4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32L476VGTx$CMSIS\Flash\STM32L4xx_1024.FLM)) + + + + + + 0 + 1 + rt_data,0x0A + + + 1 + 1 + mode_control,0x0A + + + 2 + 1 + mode_control_adjust,0x0A + + + 3 + 1 + pdctrl_data,0x0A + + + 4 + 1 + _pid + + + 5 + 1 + calib_param + + + 6 + 1 + show_loop + + + 7 + 1 + adc2_raw,0x0A + + + 8 + 1 + show_loop + + + 9 + 1 + show_actual + + + 10 + 1 + show_target + + + + + 1 + 0 + 0x1FFF75AA + 0 + + + + 0 + + + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + 0 + 0 + 0 + + + + + + + + + + 1 + 0 + 0 + 2 + 10000000 + + + + + + Application/MDK-ARM + 0 + 0 + 0 + 0 + + 1 + 1 + 2 + 0 + 0 + 0 + startup_stm32l476xx.s + startup_stm32l476xx.s + 0 + 0 + + + + + Application/User/Core + 1 + 0 + 0 + 0 + + 2 + 2 + 1 + 0 + 0 + 0 + ../Core/Src/main.c + main.c + 0 + 0 + + + 2 + 3 + 1 + 0 + 0 + 0 + ../Core/Src/gpio.c + gpio.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 + ../Core/Src/adc.c + adc.c + 0 + 0 + + + 2 + 5 + 1 + 0 + 0 + 0 + ../Core/Src/dac.c + dac.c + 0 + 0 + + + 2 + 6 + 1 + 0 + 0 + 0 + ../Core/Src/dma.c + dma.c + 0 + 0 + + + 2 + 7 + 1 + 0 + 0 + 0 + ../Core/Src/i2c.c + i2c.c + 0 + 0 + + + 2 + 8 + 1 + 0 + 0 + 0 + ../Core/Src/spi.c + spi.c + 0 + 0 + + + 2 + 9 + 1 + 0 + 0 + 0 + ../Core/Src/tim.c + tim.c + 0 + 0 + + + 2 + 10 + 1 + 0 + 0 + 0 + ../Core/Src/usart.c + usart.c + 0 + 0 + + + 2 + 11 + 1 + 0 + 0 + 0 + ../Core/Src/stm32l4xx_it.c + stm32l4xx_it.c + 0 + 0 + + + + + Drivers/STM32L4xx_HAL_Driver + 0 + 0 + 0 + 0 + + 3 + 12 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c + stm32l4xx_ll_utils.c + 0 + 0 + + + 3 + 13 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c + stm32l4xx_ll_exti.c + 0 + 0 + + + 3 + 14 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c + stm32l4xx_ll_gpio.c + 0 + 0 + + + 3 + 15 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_adc.c + stm32l4xx_ll_adc.c + 0 + 0 + + + 3 + 16 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c + stm32l4xx_ll_dma.c + 0 + 0 + + + 3 + 17 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dac.c + stm32l4xx_ll_dac.c + 0 + 0 + + + 3 + 18 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_i2c.c + stm32l4xx_ll_i2c.c + 0 + 0 + + + 3 + 19 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_spi.c + stm32l4xx_ll_spi.c + 0 + 0 + + + 3 + 20 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c + stm32l4xx_ll_pwr.c + 0 + 0 + + + 3 + 21 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_tim.c + stm32l4xx_ll_tim.c + 0 + 0 + + + 3 + 22 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c + stm32l4xx_ll_usart.c + 0 + 0 + + + 3 + 23 + 1 + 0 + 0 + 0 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c + stm32l4xx_ll_rcc.c + 0 + 0 + + + + + Drivers/CMSIS + 0 + 0 + 0 + 0 + + 4 + 24 + 1 + 0 + 0 + 0 + ../Core/Src/system_stm32l4xx.c + system_stm32l4xx.c + 0 + 0 + + + + + User + 1 + 0 + 0 + 0 + + 5 + 25 + 1 + 0 + 0 + 0 + ..\User\app.c + app.c + 0 + 0 + + + 5 + 26 + 1 + 0 + 0 + 0 + ..\User\app_flow.c + app_flow.c + 0 + 0 + + + 5 + 27 + 1 + 0 + 0 + 0 + ..\User\app_hart.c + app_hart.c + 0 + 0 + + + + + User/application + 1 + 0 + 0 + 0 + + 6 + 28 + 1 + 0 + 0 + 0 + ..\User\application\src\convert.c + convert.c + 0 + 0 + + + 6 + 29 + 1 + 0 + 0 + 0 + ..\User\application\src\params.c + params.c + 0 + 0 + + + 6 + 30 + 1 + 0 + 0 + 0 + ..\User\application\src\pdctrl.c + pdctrl.c + 0 + 0 + + + 6 + 31 + 1 + 0 + 0 + 0 + ..\User\application\src\at_hc24.c + at_hc24.c + 0 + 0 + + + 6 + 32 + 1 + 0 + 0 + 0 + ..\User\application\src\fal_execution.c + fal_execution.c + 0 + 0 + + + 6 + 33 + 1 + 0 + 0 + 0 + ..\User\application\src\params_hart.c + params_hart.c + 0 + 0 + + + + + User/application/mode + 1 + 0 + 0 + 0 + + 7 + 34 + 1 + 0 + 0 + 0 + ..\User\application\mode\mode.c + mode.c + 0 + 0 + + + 7 + 35 + 1 + 0 + 0 + 0 + ..\User\application\mode\mode_pwmp_hd.c + mode_pwmp_hd.c + 0 + 0 + + + + + User/board + 0 + 0 + 0 + 0 + + 8 + 36 + 1 + 0 + 0 + 0 + ..\User\board\src\board.c + board.c + 0 + 0 + + + 8 + 37 + 1 + 0 + 0 + 0 + ..\User\board\src\eeprom_m95.c + eeprom_m95.c + 0 + 0 + + + 8 + 38 + 1 + 0 + 0 + 0 + ..\User\board\src\eeprom_fm24.c + eeprom_fm24.c + 0 + 0 + + + 8 + 39 + 1 + 0 + 0 + 0 + ..\User\board\src\eeprom_lc02b.c + eeprom_lc02b.c + 0 + 0 + + + 8 + 40 + 1 + 0 + 0 + 0 + ..\User\board\src\rtc_rx8010.c + rtc_rx8010.c + 0 + 0 + + + 8 + 41 + 1 + 0 + 0 + 0 + ..\User\board\src\ntc_3950.c + ntc_3950.c + 0 + 0 + + + 8 + 42 + 1 + 0 + 0 + 0 + ..\User\board\src\leds.c + leds.c + 0 + 0 + + + + + User/system + 0 + 0 + 0 + 0 + + 9 + 43 + 1 + 0 + 0 + 0 + ..\User\system\src\delay.c + delay.c + 0 + 0 + + + 9 + 44 + 1 + 0 + 0 + 0 + ..\User\system\src\sys.c + sys.c + 0 + 0 + + + 9 + 45 + 1 + 0 + 0 + 0 + ..\User\system\src\btn.c + btn.c + 0 + 0 + + + 9 + 46 + 1 + 0 + 0 + 0 + ..\User\system\bsp\adcs.c + adcs.c + 0 + 0 + + + 9 + 47 + 1 + 0 + 0 + 0 + ..\User\system\bsp\dacs.c + dacs.c + 0 + 0 + + + 9 + 48 + 1 + 0 + 0 + 0 + ..\User\system\bsp\gpios.c + gpios.c + 0 + 0 + + + 9 + 49 + 1 + 0 + 0 + 0 + ..\User\system\bsp\spis.c + spis.c + 0 + 0 + + + 9 + 50 + 1 + 0 + 0 + 0 + ..\User\system\bsp\uarts.c + uarts.c + 0 + 0 + + + 9 + 51 + 1 + 0 + 0 + 0 + ..\User\system\bsp\eeprom.c + eeprom.c + 0 + 0 + + + 9 + 52 + 1 + 0 + 0 + 0 + ..\User\system\bsp\i2cs.c + i2cs.c + 0 + 0 + + + 9 + 53 + 1 + 0 + 0 + 0 + ..\User\system\bsp\pwms.c + pwms.c + 0 + 0 + + + 9 + 54 + 1 + 0 + 0 + 0 + ..\User\system\bsp\iwdgs.c + iwdgs.c + 0 + 0 + + + 9 + 55 + 1 + 0 + 0 + 0 + ..\User\system\bsp\flash.c + flash.c + 0 + 0 + + + + + User/lib + 0 + 0 + 0 + 0 + + 10 + 56 + 1 + 0 + 0 + 0 + ..\User\lib\src\debug.c + debug.c + 0 + 0 + + + 10 + 57 + 1 + 0 + 0 + 0 + ..\User\lib\src\lib.c + lib.c + 0 + 0 + + + 10 + 58 + 1 + 0 + 0 + 0 + ..\User\lib\src\malloc.c + malloc.c + 0 + 0 + + + 10 + 59 + 1 + 0 + 0 + 0 + ..\User\lib\flow\flow_core.c + flow_core.c + 0 + 0 + + + 10 + 60 + 1 + 0 + 0 + 0 + ..\User\lib\src\sqqueue.c + sqqueue.c + 0 + 0 + + + 10 + 61 + 1 + 0 + 0 + 0 + ..\User\lib\src\filter.c + filter.c + 0 + 0 + + + 10 + 62 + 1 + 0 + 0 + 0 + ..\User\lib\src\clist.c + clist.c + 0 + 0 + + + 10 + 63 + 1 + 0 + 0 + 0 + ..\User\lib\menu\menu.c + menu.c + 0 + 0 + + + 10 + 64 + 1 + 0 + 0 + 0 + ..\User\lib\src\cmac.c + cmac.c + 0 + 0 + + + 10 + 65 + 1 + 0 + 0 + 0 + ..\User\lib\src\aes.c + aes.c + 0 + 0 + + + + + User/lib/bootload + 0 + 0 + 0 + 0 + + 11 + 66 + 1 + 0 + 0 + 0 + ..\User\lib\bootload\bootload.c + bootload.c + 0 + 0 + + + 11 + 67 + 1 + 0 + 0 + 0 + ..\User\lib\bootload\ymodem.c + ymodem.c + 0 + 0 + + + + + User/lib/control + 0 + 0 + 0 + 0 + + 12 + 68 + 1 + 0 + 0 + 0 + ..\User\lib\control\src\pid.c + pid.c + 0 + 0 + + + 12 + 69 + 1 + 0 + 0 + 0 + ..\User\lib\control\src\pid_auto_tune.c + pid_auto_tune.c + 0 + 0 + + + 12 + 70 + 1 + 0 + 0 + 0 + ..\User\lib\control\src\pid_common.c + pid_common.c + 0 + 0 + + + 12 + 71 + 1 + 0 + 0 + 0 + ..\User\lib\control\src\pid_fuzzy.c + pid_fuzzy.c + 0 + 0 + + + 12 + 72 + 1 + 0 + 0 + 0 + ..\User\lib\control\src\pid_neural.c + pid_neural.c + 0 + 0 + + + 12 + 73 + 1 + 0 + 0 + 0 + ..\User\lib\control\custom\pid_c.c + pid_c.c + 0 + 0 + + + 12 + 74 + 1 + 0 + 0 + 0 + ..\User\lib\control\custom\pid_g.c + pid_g.c + 0 + 0 + + + 12 + 75 + 1 + 0 + 0 + 0 + ..\User\lib\control\custom\pid_x.c + pid_x.c + 0 + 0 + + + 12 + 76 + 1 + 0 + 0 + 0 + ..\User\lib\control\custom\pid_zh.c + pid_zh.c + 0 + 0 + + + 12 + 77 + 1 + 0 + 0 + 0 + ..\User\lib\control\custom\pid_hd.c + pid_hd.c + 0 + 0 + + + + + User/lib/flashdb + 0 + 0 + 0 + 0 + + 13 + 78 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fdb.c + fdb.c + 0 + 0 + + + 13 + 79 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fdb_kvdb.c + fdb_kvdb.c + 0 + 0 + + + 13 + 80 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fdb_tsdb.c + fdb_tsdb.c + 0 + 0 + + + 13 + 81 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fdb_utils.c + fdb_utils.c + 0 + 0 + + + 13 + 82 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fdb_file.c + fdb_file.c + 0 + 0 + + + 13 + 83 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fal_eeprom95_port.c + fal_eeprom95_port.c + 0 + 0 + + + 13 + 84 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fal_eeprom24_port.c + fal_eeprom24_port.c + 0 + 0 + + + + + User/lib/flashdb/fal + 0 + 0 + 0 + 0 + + 14 + 85 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fal\fal.c + fal.c + 0 + 0 + + + 14 + 86 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fal\fal_flash.c + fal_flash.c + 0 + 0 + + + 14 + 87 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fal\fal_partition.c + fal_partition.c + 0 + 0 + + + 14 + 88 + 1 + 0 + 0 + 0 + ..\User\lib\flashdb\fal\fal_rtt.c + fal_rtt.c + 0 + 0 + + + + + Tests + 0 + 0 + 0 + 0 + + 15 + 89 + 1 + 0 + 0 + 0 + ..\Tests\test.c + test.c + 0 + 0 + + + 15 + 90 + 1 + 0 + 0 + 0 + ..\Tests\test_bsp.c + test_bsp.c + 0 + 0 + + + + + Middlewares/Library/DSP Library/DSP Library + 0 + 0 + 0 + 0 + + 16 + 91 + 4 + 0 + 0 + 0 + ../Middlewares/ST/ARM/DSP/Lib/arm_cortexM4l_math.lib + arm_cortexM4l_math.lib + 0 + 0 + + + + + ::CMSIS + 0 + 0 + 0 + 1 + + +
diff --git a/MDK-ARM/controller-v2.uvprojx b/MDK-ARM/controller-v2.uvprojx new file mode 100644 index 0000000..6e5ce3e --- /dev/null +++ b/MDK-ARM/controller-v2.uvprojx @@ -0,0 +1,1410 @@ + + + + 2.1 + +
### uVision Project, (C) Keil Software
+ + + + controller-v2 + 0x4 + ARM-ADS + 5060960::V5.06 update 7 (build 960)::.\ARMCC + 0 + + + STM32L476VGTx + STMicroelectronics + Keil.STM32L4xx_DFP.2.6.2 + https://www.keil.com/pack/ + IRAM(0x20000000,0x00018000) IRAM2(0x10000000,0x00008000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 DSP CLOCK(12000000) ELITTLE + + + UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0STM32L4xx_1024 -FS08000000 -FL0100000 -FP0($$Device:STM32L476RGTx$CMSIS\Flash\STM32L4xx_1024.FLM)) + 0 + $$Device:STM32L476RGTx$Drivers\CMSIS\Device\ST\STM32L4xx\Include\stm32l4xx.h + + + + + + + + + + $$Device:STM32L476RGTx$CMSIS\SVD\STM32L4x6.svd + 0 + 0 + + ../Core/Inc;../Drivers/STM32L0xx_HAL_Driver/Inc;../Drivers/CMSIS/Device/ST/STM32L0xx/Include;../Drivers/CMSIS/Include;../User;../User/system/bsp;../User/board/inc;../User/lib/inc;../User/system/inc;../User/lib/font;../User/application/inc;../User/application/menus;../User/hart/inc;../User/lib/flow;../User/lib/control/inc;../User/lib/control/custom;../User/lib/lcd;../User/lib/menu;../User/lib/unity;../Tests + + + + + 0 + 0 + 0 + 0 + 1 + + controller-v2\ + controller-v2 + 1 + 0 + 1 + 1 + 0 + + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 0 + 0 + + + 0 + 0 + 0 + 0 + + + 1 + 1 + fromelf --bin --output=@L.bin !L + output-controller-v24.bat + 0 + 0 + 0 + 0 + + 1 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + 0 + + + SARMCM3.DLL + -REMAP -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + + + 1 + 0 + 0 + 1 + 1 + 4096 + + 1 + BIN\UL2CM3.DLL + "" () + + + + + 0 + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 8 + 1 + 0 + 0 + 0 + 3 + 4 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 1 + 0 + 0 + 1 + 1 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 1 + 0x8000000 + 0x100000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x8000000 + 0x6e000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x10007ff0 + 0x10 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x18000 + + + 0 + 0x10000000 + 0x7ff0 + + + + + + 1 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 1 + 1 + 0 + 3 + 3 + 1 + 1 + 0 + 0 + 0 + + --locale=english --diag_suppress=9 + V4,STM32,SLAVE,USE_FULL_LL_DRIVER,STM32L476xx,__FPU_PRESENT=1U,__FPU_USED=0U,__CC_ARM,ARM_MATH_CM4,HSE_VALUE=8000000,HSE_STARTUP_TIMEOUT=100,LSE_STARTUP_TIMEOUT=5000,LSE_VALUE=32768,EXTERNALSAI1_CLOCK_VALUE=2097000,EXTERNALSAI2_CLOCK_VALUE=2097000,HSI_VALUE=16000000,LSI_VALUE=32000,VDD_VALUE=3300,PREFETCH_ENABLE=1,INSTRUCTION_CACHE_ENABLE=1,DATA_CACHE_ENABLE=1,MSI_VALUE=16000000 + + ../Core/Inc;../Drivers/STM32L4xx_HAL_Driver/Inc;../Drivers/CMSIS/Device/ST/STM32L4xx/Include;../Drivers/CMSIS/Include;../User;../User/system/bsp;../User/board/inc;../User/lib/inc;../User/system/inc;../User/lib/font;../User/application/inc;../User/application/menus;../User/application/mode;../User/hart/inc;../User/lib/flow;../User/lib/control/inc;../User/lib/control/custom;../User/lib/lcd;../User/lib/lcd/gui/Config;../User/lib/lcd/gui/Core;../User/lib/menu;../User/lib/unity;../User/lib/flashdb;../User/lib/flashdb/fal;../User/lib/bootload;../Tests;../Middlewares/ST/ARM/DSP/Inc + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + + + + + + + + + 1 + 0 + 0 + 0 + 1 + 0 + + + + + + + + + + + + + + + Application/MDK-ARM + + + startup_stm32l476xx.s + 2 + startup_stm32l476xx.s + + + + + Application/User/Core + + + main.c + 1 + ../Core/Src/main.c + + + gpio.c + 1 + ../Core/Src/gpio.c + + + adc.c + 1 + ../Core/Src/adc.c + + + dac.c + 1 + ../Core/Src/dac.c + + + dma.c + 1 + ../Core/Src/dma.c + + + i2c.c + 1 + ../Core/Src/i2c.c + + + spi.c + 1 + ../Core/Src/spi.c + + + tim.c + 1 + ../Core/Src/tim.c + + + usart.c + 1 + ../Core/Src/usart.c + + + stm32l4xx_it.c + 1 + ../Core/Src/stm32l4xx_it.c + + + + + Drivers/STM32L4xx_HAL_Driver + + + stm32l4xx_ll_utils.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_utils.c + + + stm32l4xx_ll_exti.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_exti.c + + + stm32l4xx_ll_gpio.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_gpio.c + + + stm32l4xx_ll_adc.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_adc.c + + + stm32l4xx_ll_dma.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dma.c + + + stm32l4xx_ll_dac.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_dac.c + + + stm32l4xx_ll_i2c.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_i2c.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + stm32l4xx_ll_spi.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_spi.c + + + stm32l4xx_ll_pwr.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_pwr.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + stm32l4xx_ll_tim.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_tim.c + + + stm32l4xx_ll_usart.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_usart.c + + + stm32l4xx_ll_rcc.c + 1 + ../Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_ll_rcc.c + + + + + Drivers/CMSIS + + + system_stm32l4xx.c + 1 + ../Core/Src/system_stm32l4xx.c + + + + + User + + + app.c + 1 + ..\User\app.c + + + app_flow.c + 1 + ..\User\app_flow.c + + + app_hart.c + 1 + ..\User\app_hart.c + + + + + User/application + + + convert.c + 1 + ..\User\application\src\convert.c + + + params.c + 1 + ..\User\application\src\params.c + + + pdctrl.c + 1 + ..\User\application\src\pdctrl.c + + + at_hc24.c + 1 + ..\User\application\src\at_hc24.c + + + fal_execution.c + 1 + ..\User\application\src\fal_execution.c + + + params_hart.c + 1 + ..\User\application\src\params_hart.c + + + + + User/application/mode + + + mode.c + 1 + ..\User\application\mode\mode.c + + + mode_pwmp_hd.c + 1 + ..\User\application\mode\mode_pwmp_hd.c + + + + + User/board + + + board.c + 1 + ..\User\board\src\board.c + + + eeprom_m95.c + 1 + ..\User\board\src\eeprom_m95.c + + + eeprom_fm24.c + 1 + ..\User\board\src\eeprom_fm24.c + + + eeprom_lc02b.c + 1 + ..\User\board\src\eeprom_lc02b.c + + + rtc_rx8010.c + 1 + ..\User\board\src\rtc_rx8010.c + + + ntc_3950.c + 1 + ..\User\board\src\ntc_3950.c + + + leds.c + 1 + ..\User\board\src\leds.c + + + + + User/system + + + delay.c + 1 + ..\User\system\src\delay.c + + + sys.c + 1 + ..\User\system\src\sys.c + + + btn.c + 1 + ..\User\system\src\btn.c + + + adcs.c + 1 + ..\User\system\bsp\adcs.c + + + dacs.c + 1 + ..\User\system\bsp\dacs.c + + + gpios.c + 1 + ..\User\system\bsp\gpios.c + + + spis.c + 1 + ..\User\system\bsp\spis.c + + + uarts.c + 1 + ..\User\system\bsp\uarts.c + + + eeprom.c + 1 + ..\User\system\bsp\eeprom.c + + + i2cs.c + 1 + ..\User\system\bsp\i2cs.c + + + pwms.c + 1 + ..\User\system\bsp\pwms.c + + + iwdgs.c + 1 + ..\User\system\bsp\iwdgs.c + + + flash.c + 1 + ..\User\system\bsp\flash.c + + + + + User/lib + + + debug.c + 1 + ..\User\lib\src\debug.c + + + lib.c + 1 + ..\User\lib\src\lib.c + + + malloc.c + 1 + ..\User\lib\src\malloc.c + + + flow_core.c + 1 + ..\User\lib\flow\flow_core.c + + + sqqueue.c + 1 + ..\User\lib\src\sqqueue.c + + + filter.c + 1 + ..\User\lib\src\filter.c + + + clist.c + 1 + ..\User\lib\src\clist.c + + + menu.c + 1 + ..\User\lib\menu\menu.c + + + cmac.c + 1 + ..\User\lib\src\cmac.c + + + aes.c + 1 + ..\User\lib\src\aes.c + + + + + User/lib/bootload + + + bootload.c + 1 + ..\User\lib\bootload\bootload.c + + + ymodem.c + 1 + ..\User\lib\bootload\ymodem.c + + + + + User/lib/control + + + pid.c + 1 + ..\User\lib\control\src\pid.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + pid_auto_tune.c + 1 + ..\User\lib\control\src\pid_auto_tune.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + pid_common.c + 1 + ..\User\lib\control\src\pid_common.c + + + pid_fuzzy.c + 1 + ..\User\lib\control\src\pid_fuzzy.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + pid_neural.c + 1 + ..\User\lib\control\src\pid_neural.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + + + pid_c.c + 1 + ..\User\lib\control\custom\pid_c.c + + + pid_g.c + 1 + ..\User\lib\control\custom\pid_g.c + + + pid_x.c + 1 + ..\User\lib\control\custom\pid_x.c + + + pid_zh.c + 1 + ..\User\lib\control\custom\pid_zh.c + + + pid_hd.c + 1 + ..\User\lib\control\custom\pid_hd.c + + + + + User/lib/flashdb + + + fdb.c + 1 + ..\User\lib\flashdb\fdb.c + + + fdb_kvdb.c + 1 + ..\User\lib\flashdb\fdb_kvdb.c + + + fdb_tsdb.c + 1 + ..\User\lib\flashdb\fdb_tsdb.c + + + fdb_utils.c + 1 + ..\User\lib\flashdb\fdb_utils.c + + + fdb_file.c + 1 + ..\User\lib\flashdb\fdb_file.c + + + fal_eeprom95_port.c + 1 + ..\User\lib\flashdb\fal_eeprom95_port.c + + + fal_eeprom24_port.c + 1 + ..\User\lib\flashdb\fal_eeprom24_port.c + + + + + User/lib/flashdb/fal + + + fal.c + 1 + ..\User\lib\flashdb\fal\fal.c + + + fal_flash.c + 1 + ..\User\lib\flashdb\fal\fal_flash.c + + + fal_partition.c + 1 + ..\User\lib\flashdb\fal\fal_partition.c + + + fal_rtt.c + 1 + ..\User\lib\flashdb\fal\fal_rtt.c + + + + + Tests + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + + + + + + + + + + + + test.c + 1 + ..\Tests\test.c + + + test_bsp.c + 1 + ..\Tests\test_bsp.c + + + + + Middlewares/Library/DSP Library/DSP Library + + + 0 + 0 + 0 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + + + + + + + + + + + + arm_cortexM4l_math.lib + 4 + ../Middlewares/ST/ARM/DSP/Lib/arm_cortexM4l_math.lib + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + + + + + ::CMSIS + + + + + + + + + + + + + + + + + + + + + + controller-v2 + 1 + + + + +
diff --git a/MDK-ARM/controller-v2/ArInp.Scr b/MDK-ARM/controller-v2/ArInp.Scr new file mode 100644 index 0000000..278fbc3 --- /dev/null +++ b/MDK-ARM/controller-v2/ArInp.Scr @@ -0,0 +1,255 @@ +--create .\controller-v2\uc_gui.lib +.\controller-v2\debug.o +.\controller-v2\lib.o +.\controller-v2\malloc.o +.\controller-v2\flow_core.o +.\controller-v2\sqqueue.o +.\controller-v2\filter.o +.\controller-v2\clist.o +.\controller-v2\menu.o +.\controller-v2\cmac.o +.\controller-v2\aes.o +.\controller-v2\pid.o +.\controller-v2\pid_auto_tune.o +.\controller-v2\pid_fuzzy.o +.\controller-v2\pid_neural.o +.\controller-v2\guiaaarc.o +.\controller-v2\guiaachar.o +.\controller-v2\guiaachar2.o +.\controller-v2\guiaachar4.o +.\controller-v2\guiaacircle.o +.\controller-v2\guiaalib.o +.\controller-v2\guiaaline.o +.\controller-v2\guiaapoly.o +.\controller-v2\guiaapolyout.o +.\controller-v2\lcddummy.o +.\controller-v2\lcdnull.o +.\controller-v2\lcdwin.o +.\controller-v2\gui_x.o +.\controller-v2\lcdp0.o +.\controller-v2\lcdp2.o +.\controller-v2\lcdp4.o +.\controller-v2\gui__addspacehex.o +.\controller-v2\gui__calctextrect.o +.\controller-v2\gui__divideround.o +.\controller-v2\gui__divideround32.o +.\controller-v2\gui__getfontsizey.o +.\controller-v2\gui__getnumchars.o +.\controller-v2\gui__handleeoline.o +.\controller-v2\gui__intersectrect.o +.\controller-v2\gui__intersectrects.o +.\controller-v2\gui__memset.o +.\controller-v2\gui__memset16.o +.\controller-v2\gui__read.o +.\controller-v2\gui__reducerect.o +.\controller-v2\gui__settext.o +.\controller-v2\gui__strcmp.o +.\controller-v2\gui__strlen.o +.\controller-v2\gui__wrap.o +.\controller-v2\gui_addbin.o +.\controller-v2\gui_adddec.o +.\controller-v2\gui_adddecmin.o +.\controller-v2\gui_adddecshift.o +.\controller-v2\gui_addhex.o +.\controller-v2\gui_addkeymsghook.o +.\controller-v2\gui_alloc_allocinit.o +.\controller-v2\gui_alloc_alloczero.o +.\controller-v2\gui_bmp.o +.\controller-v2\gui_bmp_serialize.o +.\controller-v2\gui_calccolordist.o +.\controller-v2\gui_clearrectex.o +.\controller-v2\gui_color2viscolor.o +.\controller-v2\gui_cursorarrowl.o +.\controller-v2\gui_cursorarrowli.o +.\controller-v2\gui_cursorarrowlpx.o +.\controller-v2\gui_cursorarrowm.o +.\controller-v2\gui_cursorarrowmi.o +.\controller-v2\gui_cursorarrowmpx.o +.\controller-v2\gui_cursorarrows.o +.\controller-v2\gui_cursorarrowsi.o +.\controller-v2\gui_cursorarrowspx.o +.\controller-v2\gui_cursorcrossl.o +.\controller-v2\gui_cursorcrossli.o +.\controller-v2\gui_cursorcrosslpx.o +.\controller-v2\gui_cursorcrossm.o +.\controller-v2\gui_cursorcrossmi.o +.\controller-v2\gui_cursorcrossmpx.o +.\controller-v2\gui_cursorcrosss.o +.\controller-v2\gui_cursorcrosssi.o +.\controller-v2\gui_cursorcrossspx.o +.\controller-v2\gui_cursorheaderm.o +.\controller-v2\gui_cursorheadermi.o +.\controller-v2\gui_cursorheadermpx.o +.\controller-v2\gui_cursorpal.o +.\controller-v2\gui_cursorpali.o +.\controller-v2\gui_dispbin.o +.\controller-v2\gui_dispceol.o +.\controller-v2\gui_dispchar.o +.\controller-v2\gui_dispchars.o +.\controller-v2\gui_disphex.o +.\controller-v2\gui_dispstring.o +.\controller-v2\gui_dispstringat.o +.\controller-v2\gui_dispstringatceol.o +.\controller-v2\gui_dispstringhcenter.o +.\controller-v2\gui_dispstringinrect.o +.\controller-v2\gui_dispstringinrectex.o +.\controller-v2\gui_dispstringinrectmax.o +.\controller-v2\gui_dispstringlen.o +.\controller-v2\gui_drawbitmap.o +.\controller-v2\gui_drawbitmapex.o +.\controller-v2\gui_drawbitmapexp.o +.\controller-v2\gui_drawbitmapmag.o +.\controller-v2\gui_drawfocusrect.o +.\controller-v2\gui_drawgraph.o +.\controller-v2\gui_drawhline.o +.\controller-v2\gui_drawpie.o +.\controller-v2\gui_drawpixel.o +.\controller-v2\gui_drawpolyline.o +.\controller-v2\gui_drawrectex.o +.\controller-v2\gui_drawvline.o +.\controller-v2\gui_errorout.o +.\controller-v2\gui_exec.o +.\controller-v2\gui_fillpolygon.o +.\controller-v2\gui_fillrect.o +.\controller-v2\gui_fillrectex.o +.\controller-v2\gui_getbitmappixelcolor.o +.\controller-v2\gui_getbitmappixelindex.o +.\controller-v2\gui_getclientrect.o +.\controller-v2\gui_getcolor.o +.\controller-v2\gui_getdisppos.o +.\controller-v2\gui_getfont.o +.\controller-v2\gui_getfontinfo.o +.\controller-v2\gui_getfontsizey.o +.\controller-v2\gui_getlinestyle.o +.\controller-v2\gui_getstringdistx.o +.\controller-v2\gui_gettextalign.o +.\controller-v2\gui_gettextextend.o +.\controller-v2\gui_gettextmode.o +.\controller-v2\gui_getversionstring.o +.\controller-v2\gui_getysizeoffont.o +.\controller-v2\gui_goto.o +.\controller-v2\gui_initlut.o +.\controller-v2\gui_invertrect.o +.\controller-v2\gui_isinfont.o +.\controller-v2\gui_log.o +.\controller-v2\gui_mergerect.o +.\controller-v2\gui_mouse.o +.\controller-v2\gui_mouse_driverps2.o +.\controller-v2\gui_moverect.o +.\controller-v2\gui_onkey.o +.\controller-v2\gui_pen.o +.\controller-v2\gui_pid.o +.\controller-v2\gui_rectsintersect.o +.\controller-v2\gui_savecontext.o +.\controller-v2\gui_selectlayer.o +.\controller-v2\gui_selectlcd.o +.\controller-v2\gui_setcolor.o +.\controller-v2\gui_setcolorindex.o +.\controller-v2\gui_setdecchar.o +.\controller-v2\gui_setdefault.o +.\controller-v2\gui_setdrawmode.o +.\controller-v2\gui_setfont.o +.\controller-v2\gui_setlborder.o +.\controller-v2\gui_setlinestyle.o +.\controller-v2\gui_setlutcolor.o +.\controller-v2\gui_setlutcolorex.o +.\controller-v2\gui_setlutentry.o +.\controller-v2\gui_setorg.o +.\controller-v2\gui_setpixelindex.o +.\controller-v2\gui_settextalign.o +.\controller-v2\gui_settextmode.o +.\controller-v2\gui_settextstyle.o +.\controller-v2\gui_sif.o +.\controller-v2\gui_sif_prop.o +.\controller-v2\gui_touch.o +.\controller-v2\gui_touch_driveranalog.o +.\controller-v2\gui_touch_storestate.o +.\controller-v2\gui_touch_storeunstable.o +.\controller-v2\gui_uc.o +.\controller-v2\gui_uc_dispstring.o +.\controller-v2\gui_uc_encodenone.o +.\controller-v2\gui_uc_encodeutf8.o +.\controller-v2\gui_waitevent.o +.\controller-v2\gui_waitkey.o +.\controller-v2\gui_warn.o +.\controller-v2\gui2dlib.o +.\controller-v2\guialloc.o +.\controller-v2\guiarc.o +.\controller-v2\guichar.o +.\controller-v2\guicharline.o +.\controller-v2\guicharm.o +.\controller-v2\guicharp.o +.\controller-v2\guicirc.o +.\controller-v2\guicolor2index.o +.\controller-v2\guicore.o +.\controller-v2\guicurs.o +.\controller-v2\guiencjs.o +.\controller-v2\guiindex2color.o +.\controller-v2\guipolye.o +.\controller-v2\guipolym.o +.\controller-v2\guipolyr.o +.\controller-v2\guirealloc.o +.\controller-v2\guistream.o +.\controller-v2\guitask.o +.\controller-v2\guitime.o +.\controller-v2\guitimer.o +.\controller-v2\guiuc0.o +.\controller-v2\guival.o +.\controller-v2\guivalf.o +.\controller-v2\lcd.o +.\controller-v2\lcd_api.o +.\controller-v2\lcd_drawbitmap_565.o +.\controller-v2\lcd_drawbitmap_m565.o +.\controller-v2\lcd_drawvline.o +.\controller-v2\lcd_getcolorindex.o +.\controller-v2\lcd_getex.o +.\controller-v2\lcd_getnumdisplays.o +.\controller-v2\lcd_getpixelcolor.o +.\controller-v2\lcd_index2colorex.o +.\controller-v2\lcd_l0_generic.o +.\controller-v2\lcd_mirror.o +.\controller-v2\lcd_mixcolors256.o +.\controller-v2\lcd_rotate180.o +.\controller-v2\lcd_rotateccw.o +.\controller-v2\lcd_rotatecw.o +.\controller-v2\lcd_selectlcd.o +.\controller-v2\lcd_setapi.o +.\controller-v2\lcd_setcliprectex.o +.\controller-v2\lcd_updatecolorindices.o +.\controller-v2\lcdaa.o +.\controller-v2\lcdcolor.o +.\controller-v2\lcdgetp.o +.\controller-v2\lcdinfo.o +.\controller-v2\lcdinfo0.o +.\controller-v2\lcdinfo1.o +.\controller-v2\lcdl0delta.o +.\controller-v2\lcdl0mag.o +.\controller-v2\lcdp1.o +.\controller-v2\lcdp565_index2color.o +.\controller-v2\lcdpm565_index2color.o +.\controller-v2\lcdrle4.o +.\controller-v2\lcdrle8.o +.\controller-v2\lcdp111.o +.\controller-v2\lcdp222.o +.\controller-v2\lcdp233.o +.\controller-v2\lcdp323.o +.\controller-v2\lcdp332.o +.\controller-v2\lcdp444_12.o +.\controller-v2\lcdp444_12_1.o +.\controller-v2\lcdp444_16.o +.\controller-v2\lcdp555.o +.\controller-v2\lcdp556.o +.\controller-v2\lcdp565.o +.\controller-v2\lcdp655.o +.\controller-v2\lcdp8666.o +.\controller-v2\lcdp8666_1.o +.\controller-v2\lcdpm233.o +.\controller-v2\lcdpm323.o +.\controller-v2\lcdpm332.o +.\controller-v2\lcdpm444_12.o +.\controller-v2\lcdpm444_16.o +.\controller-v2\lcdpm555.o +.\controller-v2\lcdpm556.o +.\controller-v2\lcdpm565.o +.\controller-v2\lcdpm655.o +..\Middlewares\ST\ARM\DSP\Lib\arm_cortexM4l_math.lib diff --git a/MDK-ARM/output-bootload.bat b/MDK-ARM/output-bootload.bat new file mode 100644 index 0000000..19a9665 --- /dev/null +++ b/MDK-ARM/output-bootload.bat @@ -0,0 +1,5 @@ +set filename=controller-bootload +set path=controller-v2 +@echo off +copy %path%\%filename%.hex ..\Public\ļ\output +move .\%filename%.bin ..\Public\ļ\output diff --git a/MDK-ARM/output-controller-v24.bat b/MDK-ARM/output-controller-v24.bat new file mode 100644 index 0000000..a20563a --- /dev/null +++ b/MDK-ARM/output-controller-v24.bat @@ -0,0 +1,18 @@ +set project_name=controller-v2 +set version=v2.4 +set out_filename=controller +set output_file_name=%out_filename%_%version% +set path=controller-v2 + +@echo off +@REM жļǷ + +set file_path=%path%\%project_name%.hex +if exist %file_path% ( + move %file_path% ..\Public\ļ\output\%output_file_name%.hex +) + +set file_path=.\%project_name%.bin +if exist %file_path% ( + move %file_path% ..\Public\ļ\output\%output_file_name%.bin +) diff --git a/MDK-ARM/output-gui.bat b/MDK-ARM/output-gui.bat new file mode 100644 index 0000000..eae47da --- /dev/null +++ b/MDK-ARM/output-gui.bat @@ -0,0 +1,4 @@ +set filename=uc_gui +set path=controller-v2 +@echo off +copy %path%\%filename%.lib ..\User\lib\lcd diff --git a/MDK-ARM/startup_stm32l476xx.s b/MDK-ARM/startup_stm32l476xx.s new file mode 100644 index 0000000..bb44e5d --- /dev/null +++ b/MDK-ARM/startup_stm32l476xx.s @@ -0,0 +1,422 @@ +;******************************************************************************* +;* File Name : startup_stm32l476xx.s +;* Author : MCD Application Team +;* Description : STM32L476xx Ultra Low Power devices vector table for MDK-ARM toolchain. +;* This module performs: +;* - Set the initial SP +;* - Set the initial PC == Reset_Handler +;* - Set the vector table entries with the exceptions ISR address +;* - Branches to __main in the C library (which eventually +;* calls main()). +;* After Reset the Cortex-M4 processor is in Thread mode, +;* priority is Privileged, and the Stack is set to Main. +;******************************************************************************** +;* @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. +; +;******************************************************************************* +;* <<< Use Configuration Wizard in Context Menu >>> +; Amount of memory (in bytes) allocated for Stack +; Tailor this value to your application needs +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x1000 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x800 + + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; NMI Handler + DCD HardFault_Handler ; Hard Fault Handler + DCD MemManage_Handler ; MPU Fault Handler + DCD BusFault_Handler ; Bus Fault Handler + DCD UsageFault_Handler ; Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; SVCall Handler + DCD DebugMon_Handler ; Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; PendSV Handler + DCD SysTick_Handler ; SysTick Handler + + ; External Interrupts + DCD WWDG_IRQHandler ; Window WatchDog + DCD PVD_PVM_IRQHandler ; PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection + DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line + DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line + DCD FLASH_IRQHandler ; FLASH + DCD RCC_IRQHandler ; RCC + DCD EXTI0_IRQHandler ; EXTI Line0 + DCD EXTI1_IRQHandler ; EXTI Line1 + DCD EXTI2_IRQHandler ; EXTI Line2 + DCD EXTI3_IRQHandler ; EXTI Line3 + DCD EXTI4_IRQHandler ; EXTI Line4 + DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 + DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2 + DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3 + DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4 + DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5 + DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6 + DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7 + DCD ADC1_2_IRQHandler ; ADC1, ADC2 + DCD CAN1_TX_IRQHandler ; CAN1 TX + DCD CAN1_RX0_IRQHandler ; CAN1 RX0 + DCD CAN1_RX1_IRQHandler ; CAN1 RX1 + DCD CAN1_SCE_IRQHandler ; CAN1 SCE + DCD EXTI9_5_IRQHandler ; External Line[9:5]s + DCD TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15 + DCD TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16 + DCD TIM1_TRG_COM_TIM17_IRQHandler ; TIM1 Trigger and Commutation and TIM17 + DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare + DCD TIM2_IRQHandler ; TIM2 + DCD TIM3_IRQHandler ; TIM3 + DCD TIM4_IRQHandler ; TIM4 + DCD I2C1_EV_IRQHandler ; I2C1 Event + DCD I2C1_ER_IRQHandler ; I2C1 Error + DCD I2C2_EV_IRQHandler ; I2C2 Event + DCD I2C2_ER_IRQHandler ; I2C2 Error + DCD SPI1_IRQHandler ; SPI1 + DCD SPI2_IRQHandler ; SPI2 + DCD USART1_IRQHandler ; USART1 + DCD USART2_IRQHandler ; USART2 + DCD USART3_IRQHandler ; USART3 + DCD EXTI15_10_IRQHandler ; External Line[15:10] + DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line + DCD DFSDM1_FLT3_IRQHandler ; DFSDM1 Filter 3 global Interrupt + DCD TIM8_BRK_IRQHandler ; TIM8 Break Interrupt + DCD TIM8_UP_IRQHandler ; TIM8 Update Interrupt + DCD TIM8_TRG_COM_IRQHandler ; TIM8 Trigger and Commutation Interrupt + DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare Interrupt + DCD ADC3_IRQHandler ; ADC3 global Interrupt + DCD FMC_IRQHandler ; FMC + DCD SDMMC1_IRQHandler ; SDMMC1 + DCD TIM5_IRQHandler ; TIM5 + DCD SPI3_IRQHandler ; SPI3 + DCD UART4_IRQHandler ; UART4 + DCD UART5_IRQHandler ; UART5 + DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors + DCD TIM7_IRQHandler ; TIM7 + DCD DMA2_Channel1_IRQHandler ; DMA2 Channel 1 + DCD DMA2_Channel2_IRQHandler ; DMA2 Channel 2 + DCD DMA2_Channel3_IRQHandler ; DMA2 Channel 3 + DCD DMA2_Channel4_IRQHandler ; DMA2 Channel 4 + DCD DMA2_Channel5_IRQHandler ; DMA2 Channel 5 + DCD DFSDM1_FLT0_IRQHandler ; DFSDM1 Filter 0 global Interrupt + DCD DFSDM1_FLT1_IRQHandler ; DFSDM1 Filter 1 global Interrupt + DCD DFSDM1_FLT2_IRQHandler ; DFSDM1 Filter 2 global Interrupt + DCD COMP_IRQHandler ; COMP Interrupt + DCD LPTIM1_IRQHandler ; LP TIM1 interrupt + DCD LPTIM2_IRQHandler ; LP TIM2 interrupt + DCD OTG_FS_IRQHandler ; USB OTG FS + DCD DMA2_Channel6_IRQHandler ; DMA2 Channel 6 + DCD DMA2_Channel7_IRQHandler ; DMA2 Channel 7 + DCD LPUART1_IRQHandler ; LP UART1 interrupt + DCD QUADSPI_IRQHandler ; Quad SPI global interrupt + DCD I2C3_EV_IRQHandler ; I2C3 event + DCD I2C3_ER_IRQHandler ; I2C3 error + DCD SAI1_IRQHandler ; Serial Audio Interface 1 global interrupt + DCD SAI2_IRQHandler ; Serial Audio Interface 2 global interrupt + DCD SWPMI1_IRQHandler ; Serial Wire Interface 1 global interrupt + DCD TSC_IRQHandler ; Touch Sense Controller global interrupt + DCD LCD_IRQHandler ; LCD global interrupt + DCD 0 ; Reserved + DCD RNG_IRQHandler ; RNG global interrupt + DCD FPU_IRQHandler ; FPU + +__Vectors_End + +__Vectors_Size EQU __Vectors_End - __Vectors + + AREA |.text|, CODE, READONLY + +; Reset handler +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; Dummy Exception Handlers (infinite loops which can be modified) + +NMI_Handler PROC + EXPORT NMI_Handler [WEAK] + B . + ENDP +HardFault_Handler\ + PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP +MemManage_Handler\ + PROC + EXPORT MemManage_Handler [WEAK] + B . + ENDP +BusFault_Handler\ + PROC + EXPORT BusFault_Handler [WEAK] + B . + ENDP +UsageFault_Handler\ + PROC + EXPORT UsageFault_Handler [WEAK] + B . + ENDP +SVC_Handler PROC + EXPORT SVC_Handler [WEAK] + B . + ENDP +DebugMon_Handler\ + PROC + EXPORT DebugMon_Handler [WEAK] + B . + ENDP +PendSV_Handler PROC + EXPORT PendSV_Handler [WEAK] + B . + ENDP +SysTick_Handler PROC + EXPORT SysTick_Handler [WEAK] + B . + ENDP + +Default_Handler PROC + + EXPORT WWDG_IRQHandler [WEAK] + EXPORT PVD_PVM_IRQHandler [WEAK] + EXPORT TAMP_STAMP_IRQHandler [WEAK] + EXPORT RTC_WKUP_IRQHandler [WEAK] + EXPORT FLASH_IRQHandler [WEAK] + EXPORT RCC_IRQHandler [WEAK] + EXPORT EXTI0_IRQHandler [WEAK] + EXPORT EXTI1_IRQHandler [WEAK] + EXPORT EXTI2_IRQHandler [WEAK] + EXPORT EXTI3_IRQHandler [WEAK] + EXPORT EXTI4_IRQHandler [WEAK] + EXPORT DMA1_Channel1_IRQHandler [WEAK] + EXPORT DMA1_Channel2_IRQHandler [WEAK] + EXPORT DMA1_Channel3_IRQHandler [WEAK] + EXPORT DMA1_Channel4_IRQHandler [WEAK] + EXPORT DMA1_Channel5_IRQHandler [WEAK] + EXPORT DMA1_Channel6_IRQHandler [WEAK] + EXPORT DMA1_Channel7_IRQHandler [WEAK] + EXPORT ADC1_2_IRQHandler [WEAK] + EXPORT CAN1_TX_IRQHandler [WEAK] + EXPORT CAN1_RX0_IRQHandler [WEAK] + EXPORT CAN1_RX1_IRQHandler [WEAK] + EXPORT CAN1_SCE_IRQHandler [WEAK] + EXPORT EXTI9_5_IRQHandler [WEAK] + EXPORT TIM1_BRK_TIM15_IRQHandler [WEAK] + EXPORT TIM1_UP_TIM16_IRQHandler [WEAK] + EXPORT TIM1_TRG_COM_TIM17_IRQHandler [WEAK] + EXPORT TIM1_CC_IRQHandler [WEAK] + EXPORT TIM2_IRQHandler [WEAK] + EXPORT TIM3_IRQHandler [WEAK] + EXPORT TIM4_IRQHandler [WEAK] + EXPORT I2C1_EV_IRQHandler [WEAK] + EXPORT I2C1_ER_IRQHandler [WEAK] + EXPORT I2C2_EV_IRQHandler [WEAK] + EXPORT I2C2_ER_IRQHandler [WEAK] + EXPORT SPI1_IRQHandler [WEAK] + EXPORT SPI2_IRQHandler [WEAK] + EXPORT USART1_IRQHandler [WEAK] + EXPORT USART2_IRQHandler [WEAK] + EXPORT USART3_IRQHandler [WEAK] + EXPORT EXTI15_10_IRQHandler [WEAK] + EXPORT RTC_Alarm_IRQHandler [WEAK] + EXPORT DFSDM1_FLT3_IRQHandler [WEAK] + EXPORT TIM8_BRK_IRQHandler [WEAK] + EXPORT TIM8_UP_IRQHandler [WEAK] + EXPORT TIM8_TRG_COM_IRQHandler [WEAK] + EXPORT TIM8_CC_IRQHandler [WEAK] + EXPORT ADC3_IRQHandler [WEAK] + EXPORT FMC_IRQHandler [WEAK] + EXPORT SDMMC1_IRQHandler [WEAK] + EXPORT TIM5_IRQHandler [WEAK] + EXPORT SPI3_IRQHandler [WEAK] + EXPORT UART4_IRQHandler [WEAK] + EXPORT UART5_IRQHandler [WEAK] + EXPORT TIM6_DAC_IRQHandler [WEAK] + EXPORT TIM7_IRQHandler [WEAK] + EXPORT DMA2_Channel1_IRQHandler [WEAK] + EXPORT DMA2_Channel2_IRQHandler [WEAK] + EXPORT DMA2_Channel3_IRQHandler [WEAK] + EXPORT DMA2_Channel4_IRQHandler [WEAK] + EXPORT DMA2_Channel5_IRQHandler [WEAK] + EXPORT DFSDM1_FLT0_IRQHandler [WEAK] + EXPORT DFSDM1_FLT1_IRQHandler [WEAK] + EXPORT DFSDM1_FLT2_IRQHandler [WEAK] + EXPORT COMP_IRQHandler [WEAK] + EXPORT LPTIM1_IRQHandler [WEAK] + EXPORT LPTIM2_IRQHandler [WEAK] + EXPORT OTG_FS_IRQHandler [WEAK] + EXPORT DMA2_Channel6_IRQHandler [WEAK] + EXPORT DMA2_Channel7_IRQHandler [WEAK] + EXPORT LPUART1_IRQHandler [WEAK] + EXPORT QUADSPI_IRQHandler [WEAK] + EXPORT I2C3_EV_IRQHandler [WEAK] + EXPORT I2C3_ER_IRQHandler [WEAK] + EXPORT SAI1_IRQHandler [WEAK] + EXPORT SAI2_IRQHandler [WEAK] + EXPORT SWPMI1_IRQHandler [WEAK] + EXPORT TSC_IRQHandler [WEAK] + EXPORT LCD_IRQHandler [WEAK] + EXPORT RNG_IRQHandler [WEAK] + EXPORT FPU_IRQHandler [WEAK] + +WWDG_IRQHandler +PVD_PVM_IRQHandler +TAMP_STAMP_IRQHandler +RTC_WKUP_IRQHandler +FLASH_IRQHandler +RCC_IRQHandler +EXTI0_IRQHandler +EXTI1_IRQHandler +EXTI2_IRQHandler +EXTI3_IRQHandler +EXTI4_IRQHandler +DMA1_Channel1_IRQHandler +DMA1_Channel2_IRQHandler +DMA1_Channel3_IRQHandler +DMA1_Channel4_IRQHandler +DMA1_Channel5_IRQHandler +DMA1_Channel6_IRQHandler +DMA1_Channel7_IRQHandler +ADC1_2_IRQHandler +CAN1_TX_IRQHandler +CAN1_RX0_IRQHandler +CAN1_RX1_IRQHandler +CAN1_SCE_IRQHandler +EXTI9_5_IRQHandler +TIM1_BRK_TIM15_IRQHandler +TIM1_UP_TIM16_IRQHandler +TIM1_TRG_COM_TIM17_IRQHandler +TIM1_CC_IRQHandler +TIM2_IRQHandler +TIM3_IRQHandler +TIM4_IRQHandler +I2C1_EV_IRQHandler +I2C1_ER_IRQHandler +I2C2_EV_IRQHandler +I2C2_ER_IRQHandler +SPI1_IRQHandler +SPI2_IRQHandler +USART1_IRQHandler +USART2_IRQHandler +USART3_IRQHandler +EXTI15_10_IRQHandler +RTC_Alarm_IRQHandler +DFSDM1_FLT3_IRQHandler +TIM8_BRK_IRQHandler +TIM8_UP_IRQHandler +TIM8_TRG_COM_IRQHandler +TIM8_CC_IRQHandler +ADC3_IRQHandler +FMC_IRQHandler +SDMMC1_IRQHandler +TIM5_IRQHandler +SPI3_IRQHandler +UART4_IRQHandler +UART5_IRQHandler +TIM6_DAC_IRQHandler +TIM7_IRQHandler +DMA2_Channel1_IRQHandler +DMA2_Channel2_IRQHandler +DMA2_Channel3_IRQHandler +DMA2_Channel4_IRQHandler +DMA2_Channel5_IRQHandler +DFSDM1_FLT0_IRQHandler +DFSDM1_FLT1_IRQHandler +DFSDM1_FLT2_IRQHandler +COMP_IRQHandler +LPTIM1_IRQHandler +LPTIM2_IRQHandler +OTG_FS_IRQHandler +DMA2_Channel6_IRQHandler +DMA2_Channel7_IRQHandler +LPUART1_IRQHandler +QUADSPI_IRQHandler +I2C3_EV_IRQHandler +I2C3_ER_IRQHandler +SAI1_IRQHandler +SAI2_IRQHandler +SWPMI1_IRQHandler +TSC_IRQHandler +LCD_IRQHandler +RNG_IRQHandler +FPU_IRQHandler + + B . + + ENDP + + ALIGN + +;******************************************************************************* +; User Stack and Heap initialization +;******************************************************************************* + IF :DEF:__MICROLIB + + EXPORT __initial_sp + EXPORT __heap_base + EXPORT __heap_limit + + ELSE + + IMPORT __use_two_region_memory + EXPORT __user_initial_stackheap + +__user_initial_stackheap + + LDR R0, = Heap_Mem + LDR R1, =(Stack_Mem + Stack_Size) + LDR R2, = (Heap_Mem + Heap_Size) + LDR R3, = Stack_Mem + BX LR + + ALIGN + + ENDIF + + END + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a585c2f --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +current_time=$(shell date +%Y%m%d%H%M) +# 获得当前git的用户邮箱 +current_user=$(shell git config user.email) + +.PHONY:clean cc + +all: clean + +cc: + git rm -r --cached . + git add . + git commit -m "$(current_user) batch push $(current_time)" + git push origin develop + +clean: + cmd /c keilkill.bat + + diff --git a/Middlewares/ST/ARM/DSP/Inc/arm_math.h b/Middlewares/ST/ARM/DSP/Inc/arm_math.h new file mode 100644 index 0000000..ea9dd26 --- /dev/null +++ b/Middlewares/ST/ARM/DSP/Inc/arm_math.h @@ -0,0 +1,7157 @@ +/****************************************************************************** + * @file arm_math.h + * @brief Public header file for CMSIS DSP LibraryU + * @version V1.5.3 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (c) 2010-2018 Arm Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + \mainpage CMSIS DSP Software Library + * + * Introduction + * ------------ + * + * This user manual describes the CMSIS DSP software library, + * a suite of common signal processing functions for use on Cortex-M processor based devices. + * + * The library is divided into a number of functions each covering a specific category: + * - Basic math functions + * - Fast math functions + * - Complex math functions + * - Filters + * - Matrix functions + * - Transforms + * - Motor control functions + * - Statistical functions + * - Support functions + * - Interpolation functions + * + * The library has separate functions for operating on 8-bit integers, 16-bit integers, + * 32-bit integer and 32-bit floating-point values. + * + * Using the Library + * ------------ + * + * The library installer contains prebuilt versions of the libraries in the Lib folder. + * - arm_cortexM7lfdp_math.lib (Cortex-M7, Little endian, Double Precision Floating Point Unit) + * - arm_cortexM7bfdp_math.lib (Cortex-M7, Big endian, Double Precision Floating Point Unit) + * - arm_cortexM7lfsp_math.lib (Cortex-M7, Little endian, Single Precision Floating Point Unit) + * - arm_cortexM7bfsp_math.lib (Cortex-M7, Big endian and Single Precision Floating Point Unit on) + * - arm_cortexM7l_math.lib (Cortex-M7, Little endian) + * - arm_cortexM7b_math.lib (Cortex-M7, Big endian) + * - arm_cortexM4lf_math.lib (Cortex-M4, Little endian, Floating Point Unit) + * - arm_cortexM4bf_math.lib (Cortex-M4, Big endian, Floating Point Unit) + * - arm_cortexM4l_math.lib (Cortex-M4, Little endian) + * - arm_cortexM4b_math.lib (Cortex-M4, Big endian) + * - arm_cortexM3l_math.lib (Cortex-M3, Little endian) + * - arm_cortexM3b_math.lib (Cortex-M3, Big endian) + * - arm_cortexM0l_math.lib (Cortex-M0 / Cortex-M0+, Little endian) + * - arm_cortexM0b_math.lib (Cortex-M0 / Cortex-M0+, Big endian) + * - arm_ARMv8MBLl_math.lib (Armv8-M Baseline, Little endian) + * - arm_ARMv8MMLl_math.lib (Armv8-M Mainline, Little endian) + * - arm_ARMv8MMLlfsp_math.lib (Armv8-M Mainline, Little endian, Single Precision Floating Point Unit) + * - arm_ARMv8MMLld_math.lib (Armv8-M Mainline, Little endian, DSP instructions) + * - arm_ARMv8MMLldfsp_math.lib (Armv8-M Mainline, Little endian, DSP instructions, Single Precision Floating Point Unit) + * + * The library functions are declared in the public file arm_math.h which is placed in the Include folder. + * Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single + * public header file arm_math.h for Cortex-M cores with little endian and big endian. Same header file will be used for floating point unit(FPU) variants. + * Define the appropriate preprocessor macro ARM_MATH_CM7 or ARM_MATH_CM4 or ARM_MATH_CM3 or + * ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application. + * For Armv8-M cores define preprocessor macro ARM_MATH_ARMV8MBL or ARM_MATH_ARMV8MML. + * Set preprocessor macro __DSP_PRESENT if Armv8-M Mainline core supports DSP instructions. + * + * + * Examples + * -------- + * + * The library ships with a number of examples which demonstrate how to use the library functions. + * + * Toolchain Support + * ------------ + * + * The library has been developed and tested with MDK version 5.14.0.0 + * The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly. + * + * Building the Library + * ------------ + * + * The library installer contains a project file to rebuild libraries on MDK toolchain in the CMSIS\\DSP_Lib\\Source\\ARM folder. + * - arm_cortexM_math.uvprojx + * + * + * The libraries can be built by opening the arm_cortexM_math.uvprojx project in MDK-ARM, selecting a specific target, and defining the optional preprocessor macros detailed above. + * + * Preprocessor Macros + * ------------ + * + * Each library project have different preprocessor macros. + * + * - UNALIGNED_SUPPORT_DISABLE: + * + * Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access + * + * - ARM_MATH_BIG_ENDIAN: + * + * Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets. + * + * - ARM_MATH_MATRIX_CHECK: + * + * Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices + * + * - ARM_MATH_ROUNDING: + * + * Define macro ARM_MATH_ROUNDING for rounding on support functions + * + * - ARM_MATH_CMx: + * + * Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target + * and ARM_MATH_CM0 for building library on Cortex-M0 target, ARM_MATH_CM0PLUS for building library on Cortex-M0+ target, and + * ARM_MATH_CM7 for building the library on cortex-M7. + * + * - ARM_MATH_ARMV8MxL: + * + * Define macro ARM_MATH_ARMV8MBL for building the library on Armv8-M Baseline target, ARM_MATH_ARMV8MML for building library + * on Armv8-M Mainline target. + * + * - __FPU_PRESENT: + * + * Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for floating point libraries. + * + * - __DSP_PRESENT: + * + * Initialize macro __DSP_PRESENT = 1 when Armv8-M Mainline core supports DSP instructions. + * + *
+ * CMSIS-DSP in ARM::CMSIS Pack + * ----------------------------- + * + * The following files relevant to CMSIS-DSP are present in the ARM::CMSIS Pack directories: + * |File/Folder |Content | + * |------------------------------|------------------------------------------------------------------------| + * |\b CMSIS\\Documentation\\DSP | This documentation | + * |\b CMSIS\\DSP_Lib | Software license agreement (license.txt) | + * |\b CMSIS\\DSP_Lib\\Examples | Example projects demonstrating the usage of the library functions | + * |\b CMSIS\\DSP_Lib\\Source | Source files for rebuilding the library | + * + *
+ * Revision History of CMSIS-DSP + * ------------ + * Please refer to \ref ChangeLog_pg. + * + * Copyright Notice + * ------------ + * + * Copyright (C) 2010-2015 Arm Limited. All rights reserved. + */ + + +/** + * @defgroup groupMath Basic Math Functions + */ + +/** + * @defgroup groupFastMath Fast Math Functions + * This set of functions provides a fast approximation to sine, cosine, and square root. + * As compared to most of the other functions in the CMSIS math library, the fast math functions + * operate on individual values and not arrays. + * There are separate functions for Q15, Q31, and floating-point data. + * + */ + +/** + * @defgroup groupCmplxMath Complex Math Functions + * This set of functions operates on complex data vectors. + * The data in the complex arrays is stored in an interleaved fashion + * (real, imag, real, imag, ...). + * In the API functions, the number of samples in a complex array refers + * to the number of complex values; the array contains twice this number of + * real values. + */ + +/** + * @defgroup groupFilters Filtering Functions + */ + +/** + * @defgroup groupMatrix Matrix Functions + * + * This set of functions provides basic matrix math operations. + * The functions operate on matrix data structures. For example, + * the type + * definition for the floating-point matrix structure is shown + * below: + *
+ *     typedef struct
+ *     {
+ *       uint16_t numRows;     // number of rows of the matrix.
+ *       uint16_t numCols;     // number of columns of the matrix.
+ *       float32_t *pData;     // points to the data of the matrix.
+ *     } arm_matrix_instance_f32;
+ * 
+ * There are similar definitions for Q15 and Q31 data types. + * + * The structure specifies the size of the matrix and then points to + * an array of data. The array is of size numRows X numCols + * and the values are arranged in row order. That is, the + * matrix element (i, j) is stored at: + *
+ *     pData[i*numCols + j]
+ * 
+ * + * \par Init Functions + * There is an associated initialization function for each type of matrix + * data structure. + * The initialization function sets the values of the internal structure fields. + * Refer to the function arm_mat_init_f32(), arm_mat_init_q31() + * and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively. + * + * \par + * Use of the initialization function is optional. However, if initialization function is used + * then the instance structure cannot be placed into a const data section. + * To place the instance structure in a const data + * section, manually initialize the data structure. For example: + *
+ * arm_matrix_instance_f32 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q31 S = {nRows, nColumns, pData};
+ * arm_matrix_instance_q15 S = {nRows, nColumns, pData};
+ * 
+ * where nRows specifies the number of rows, nColumns + * specifies the number of columns, and pData points to the + * data array. + * + * \par Size Checking + * By default all of the matrix functions perform size checking on the input and + * output matrices. For example, the matrix addition function verifies that the + * two input matrices and the output matrix all have the same number of rows and + * columns. If the size check fails the functions return: + *
+ *     ARM_MATH_SIZE_MISMATCH
+ * 
+ * Otherwise the functions return + *
+ *     ARM_MATH_SUCCESS
+ * 
+ * There is some overhead associated with this matrix size checking. + * The matrix size checking is enabled via the \#define + *
+ *     ARM_MATH_MATRIX_CHECK
+ * 
+ * within the library project settings. By default this macro is defined + * and size checking is enabled. By changing the project settings and + * undefining this macro size checking is eliminated and the functions + * run a bit faster. With size checking disabled the functions always + * return ARM_MATH_SUCCESS. + */ + +/** + * @defgroup groupTransforms Transform Functions + */ + +/** + * @defgroup groupController Controller Functions + */ + +/** + * @defgroup groupStats Statistics Functions + */ +/** + * @defgroup groupSupport Support Functions + */ + +/** + * @defgroup groupInterpolation Interpolation Functions + * These functions perform 1- and 2-dimensional interpolation of data. + * Linear interpolation is used for 1-dimensional data and + * bilinear interpolation is used for 2-dimensional data. + */ + +/** + * @defgroup groupExamples Examples + */ +#ifndef _ARM_MATH_H +#define _ARM_MATH_H + +/* Compiler specific diagnostic adjustment */ +#if defined ( __CC_ARM ) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + +#elif defined ( __GNUC__ ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +#elif defined ( __ICCARM__ ) + +#elif defined ( __TI_ARM__ ) + +#elif defined ( __CSMC__ ) + +#elif defined ( __TASKING__ ) + +#else + #error Unknown compiler +#endif + + +#define __CMSIS_GENERIC /* disable NVIC and Systick functions */ + +#if defined(ARM_MATH_CM7) + #include "core_cm7.h" + #define ARM_MATH_DSP +#elif defined (ARM_MATH_CM4) + #include "core_cm4.h" + #define ARM_MATH_DSP +#elif defined (ARM_MATH_CM3) + #include "core_cm3.h" +#elif defined (ARM_MATH_CM0) + #include "core_cm0.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_CM0PLUS) + #include "core_cm0plus.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_ARMV8MBL) + #include "core_armv8mbl.h" + #define ARM_MATH_CM0_FAMILY +#elif defined (ARM_MATH_ARMV8MML) + #include "core_armv8mml.h" + #if (defined (__DSP_PRESENT) && (__DSP_PRESENT == 1)) + #define ARM_MATH_DSP + #endif +#else + #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS, ARM_MATH_CM0, ARM_MATH_ARMV8MBL, ARM_MATH_ARMV8MML" +#endif + +#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */ +#include "string.h" +#include "math.h" +#ifdef __cplusplus +extern "C" +{ +#endif + + + /** + * @brief Macros required for reciprocal calculation in Normalized LMS + */ + +#define DELTA_Q31 (0x100) +#define DELTA_Q15 0x5 +#define INDEX_MASK 0x0000003F +#ifndef PI + #define PI 3.14159265358979f +#endif + + /** + * @brief Macros required for SINE and COSINE Fast math approximations + */ + +#define FAST_MATH_TABLE_SIZE 512 +#define FAST_MATH_Q31_SHIFT (32 - 10) +#define FAST_MATH_Q15_SHIFT (16 - 10) +#define CONTROLLER_Q31_SHIFT (32 - 9) +#define TABLE_SPACING_Q31 0x400000 +#define TABLE_SPACING_Q15 0x80 + + /** + * @brief Macros required for SINE and COSINE Controller functions + */ + /* 1.31(q31) Fixed value of 2/360 */ + /* -1 to +1 is divided into 360 values so total spacing is (2/360) */ +#define INPUT_SPACING 0xB60B61 + + /** + * @brief Macro for Unaligned Support + */ +#ifndef UNALIGNED_SUPPORT_DISABLE + #define ALIGN4 +#else + #if defined (__GNUC__) + #define ALIGN4 __attribute__((aligned(4))) + #else + #define ALIGN4 __align(4) + #endif +#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */ + + /** + * @brief Error status returned by some functions in the library. + */ + + typedef enum + { + ARM_MATH_SUCCESS = 0, /**< No error */ + ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */ + ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */ + ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */ + ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */ + ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */ + ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */ + } arm_status; + + /** + * @brief 8-bit fractional data type in 1.7 format. + */ + typedef int8_t q7_t; + + /** + * @brief 16-bit fractional data type in 1.15 format. + */ + typedef int16_t q15_t; + + /** + * @brief 32-bit fractional data type in 1.31 format. + */ + typedef int32_t q31_t; + + /** + * @brief 64-bit fractional data type in 1.63 format. + */ + typedef int64_t q63_t; + + /** + * @brief 32-bit floating-point type definition. + */ + typedef float float32_t; + + /** + * @brief 64-bit floating-point type definition. + */ + typedef double float64_t; + + /** + * @brief definition to read/write two 16 bit values. + */ +#if defined ( __CC_ARM ) + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE __attribute__((always_inline)) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE __attribute__((always_inline)) + +#elif defined ( __GNUC__ ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE __attribute__((always_inline)) + +#elif defined ( __ICCARM__ ) + #define __SIMD32_TYPE int32_t __packed + #define CMSIS_UNUSED + #define CMSIS_INLINE + +#elif defined ( __TI_ARM__ ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED __attribute__((unused)) + #define CMSIS_INLINE + +#elif defined ( __CSMC__ ) + #define __SIMD32_TYPE int32_t + #define CMSIS_UNUSED + #define CMSIS_INLINE + +#elif defined ( __TASKING__ ) + #define __SIMD32_TYPE __unaligned int32_t + #define CMSIS_UNUSED + #define CMSIS_INLINE + +#else + #error Unknown compiler +#endif + +#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr)) +#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr)) +#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr)) +#define __SIMD64(addr) (*(int64_t **) & (addr)) + +#if !defined (ARM_MATH_DSP) + /** + * @brief definition to pack two 16 bit values. + */ +#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \ + (((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) ) +#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \ + (((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) ) + +#endif /* !defined (ARM_MATH_DSP) */ + + /** + * @brief definition to pack four 8 bit values. + */ +#ifndef ARM_MATH_BIG_ENDIAN + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v3) << 24) & (int32_t)0xFF000000) ) +#else + +#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \ + (((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \ + (((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \ + (((int32_t)(v0) << 24) & (int32_t)0xFF000000) ) + +#endif + + + /** + * @brief Clips Q63 to Q31 values. + */ + CMSIS_INLINE __STATIC_INLINE q31_t clip_q63_to_q31( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x; + } + + /** + * @brief Clips Q63 to Q15 values. + */ + CMSIS_INLINE __STATIC_INLINE q15_t clip_q63_to_q15( + q63_t x) + { + return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ? + ((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15); + } + + /** + * @brief Clips Q31 to Q7 values. + */ + CMSIS_INLINE __STATIC_INLINE q7_t clip_q31_to_q7( + q31_t x) + { + return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ? + ((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x; + } + + /** + * @brief Clips Q31 to Q15 values. + */ + CMSIS_INLINE __STATIC_INLINE q15_t clip_q31_to_q15( + q31_t x) + { + return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ? + ((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x; + } + + /** + * @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format. + */ + + CMSIS_INLINE __STATIC_INLINE q63_t mult32x64( + q63_t x, + q31_t y) + { + return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) + + (((q63_t) (x >> 32) * y))); + } + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type. + */ + + CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q31( + q31_t in, + q31_t * dst, + q31_t * pRecipTable) + { + q31_t out; + uint32_t tempVal; + uint32_t index, i; + uint32_t signBits; + + if (in > 0) + { + signBits = ((uint32_t) (__CLZ( in) - 1)); + } + else + { + signBits = ((uint32_t) (__CLZ(-in) - 1)); + } + + /* Convert input sample to 1.31 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 24); + index = (index & INDEX_MASK); + + /* 1.31 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0U; i < 2U; i++) + { + tempVal = (uint32_t) (((q63_t) in * out) >> 31); + tempVal = 0x7FFFFFFFu - tempVal; + /* 1.31 with exp 1 */ + /* out = (q31_t) (((q63_t) out * tempVal) >> 30); */ + out = clip_q63_to_q31(((q63_t) out * tempVal) >> 30); + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1U); + } + + + /** + * @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type. + */ + CMSIS_INLINE __STATIC_INLINE uint32_t arm_recip_q15( + q15_t in, + q15_t * dst, + q15_t * pRecipTable) + { + q15_t out = 0; + uint32_t tempVal = 0; + uint32_t index = 0, i = 0; + uint32_t signBits = 0; + + if (in > 0) + { + signBits = ((uint32_t)(__CLZ( in) - 17)); + } + else + { + signBits = ((uint32_t)(__CLZ(-in) - 17)); + } + + /* Convert input sample to 1.15 format */ + in = (in << signBits); + + /* calculation of index for initial approximated Val */ + index = (uint32_t)(in >> 8); + index = (index & INDEX_MASK); + + /* 1.15 with exp 1 */ + out = pRecipTable[index]; + + /* calculation of reciprocal value */ + /* running approximation for two iterations */ + for (i = 0U; i < 2U; i++) + { + tempVal = (uint32_t) (((q31_t) in * out) >> 15); + tempVal = 0x7FFFu - tempVal; + /* 1.15 with exp 1 */ + out = (q15_t) (((q31_t) out * tempVal) >> 14); + /* out = clip_q31_to_q15(((q31_t) out * tempVal) >> 14); */ + } + + /* write output */ + *dst = out; + + /* return num of signbits of out = 1/in value */ + return (signBits + 1); + } + + +/* + * @brief C custom defined intrinsic function for M3 and M0 processors + */ +#if !defined (ARM_MATH_DSP) + + /* + * @brief C custom defined QADD8 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QADD8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) + (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) + (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) + (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) + (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QSUB8 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB8( + uint32_t x, + uint32_t y) + { + q31_t r, s, t, u; + + r = __SSAT(((((q31_t)x << 24) >> 24) - (((q31_t)y << 24) >> 24)), 8) & (int32_t)0x000000FF; + s = __SSAT(((((q31_t)x << 16) >> 24) - (((q31_t)y << 16) >> 24)), 8) & (int32_t)0x000000FF; + t = __SSAT(((((q31_t)x << 8) >> 24) - (((q31_t)y << 8) >> 24)), 8) & (int32_t)0x000000FF; + u = __SSAT(((((q31_t)x ) >> 24) - (((q31_t)y ) >> 24)), 8) & (int32_t)0x000000FF; + + return ((uint32_t)((u << 24) | (t << 16) | (s << 8) | (r ))); + } + + + /* + * @brief C custom defined QADD16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QADD16( + uint32_t x, + uint32_t y) + { +/* q31_t r, s; without initialisation 'arm_offset_q15 test' fails but 'intrinsic' tests pass! for armCC */ + q31_t r = 0, s = 0; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHADD16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHADD16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSUB16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSUB16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHSUB16( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QASX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHASX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHASX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) - (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) + (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined QSAX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __QSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = __SSAT(((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)), 16) & (int32_t)0x0000FFFF; + s = __SSAT(((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)), 16) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SHSAX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SHSAX( + uint32_t x, + uint32_t y) + { + q31_t r, s; + + r = (((((q31_t)x << 16) >> 16) + (((q31_t)y ) >> 16)) >> 1) & (int32_t)0x0000FFFF; + s = (((((q31_t)x ) >> 16) - (((q31_t)y << 16) >> 16)) >> 1) & (int32_t)0x0000FFFF; + + return ((uint32_t)((s << 16) | (r ))); + } + + + /* + * @brief C custom defined SMUSDX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSDX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + /* + * @brief C custom defined SMUADX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUADX( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) )); + } + + + /* + * @brief C custom defined QADD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE int32_t __QADD( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x + (q31_t)y))); + } + + + /* + * @brief C custom defined QSUB for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE int32_t __QSUB( + int32_t x, + int32_t y) + { + return ((int32_t)(clip_q63_to_q31((q63_t)x - (q31_t)y))); + } + + + /* + * @brief C custom defined SMLAD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMLAD( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLADX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMLADX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLSDX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMLSDX( + uint32_t x, + uint32_t y, + uint32_t sum) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q31_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALD( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) + ((q15_t) x * (q15_t) y)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMLALDX for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint64_t __SMLALDX( + uint32_t x, + uint32_t y, + uint64_t sum) + { +/* return (sum + ((q15_t) (x >> 16) * (q15_t) y)) + ((q15_t) x * (q15_t) (y >> 16)); */ + return ((uint64_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y ) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y << 16) >> 16)) + + ( ((q63_t)sum ) ) )); + } + + + /* + * @brief C custom defined SMUAD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUAD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) + + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SMUSD for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SMUSD( + uint32_t x, + uint32_t y) + { + return ((uint32_t)(((((q31_t)x << 16) >> 16) * (((q31_t)y << 16) >> 16)) - + ((((q31_t)x ) >> 16) * (((q31_t)y ) >> 16)) )); + } + + + /* + * @brief C custom defined SXTB16 for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE uint32_t __SXTB16( + uint32_t x) + { + return ((uint32_t)(((((q31_t)x << 24) >> 24) & (q31_t)0x0000FFFF) | + ((((q31_t)x << 8) >> 8) & (q31_t)0xFFFF0000) )); + } + + /* + * @brief C custom defined SMMLA for M3 and M0 processors + */ + CMSIS_INLINE __STATIC_INLINE int32_t __SMMLA( + int32_t x, + int32_t y, + int32_t sum) + { + return (sum + (int32_t) (((int64_t) x * y) >> 32)); + } + +#endif /* !defined (ARM_MATH_DSP) */ + + + /** + * @brief Instance structure for the Q7 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q7; + + /** + * @brief Instance structure for the Q15 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + } arm_fir_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of filter coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + } arm_fir_instance_f32; + + + /** + * @brief Processing function for the Q7 FIR filter. + * @param[in] S points to an instance of the Q7 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q7( + const arm_fir_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 FIR filter. + * @param[in,out] S points to an instance of the Q7 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed. + */ + void arm_fir_init_q7( + arm_fir_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR filter. + * @param[in] S points to an instance of the Q15 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q15( + const arm_fir_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR filter. + * @param[in,out] S points to an instance of the Q15 FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + * @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if + * numTaps is not a supported value. + */ + arm_status arm_fir_init_q15( + arm_fir_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR filter. + * @param[in] S points to an instance of the Q31 FIR filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_fast_q31( + const arm_fir_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR filter. + * @param[in,out] S points to an instance of the Q31 FIR structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_q31( + arm_fir_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR filter. + * @param[in] S points to an instance of the floating-point FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_f32( + const arm_fir_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR filter. + * @param[in,out] S points to an instance of the floating-point FIR filter structure. + * @param[in] numTaps Number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of samples that are processed at a time. + */ + void arm_fir_init_f32( + arm_fir_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 Biquad cascade filter. + */ + typedef struct + { + int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q15; + + /** + * @brief Instance structure for the Q31 Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */ + } arm_biquad_casd_df1_inst_q31; + + /** + * @brief Instance structure for the floating-point Biquad cascade filter. + */ + typedef struct + { + uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_casd_df1_inst_f32; + + + /** + * @brief Processing function for the Q15 Biquad cascade filter. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q15( + arm_biquad_casd_df1_inst_q15 * S, + uint8_t numStages, + q15_t * pCoeffs, + q15_t * pState, + int8_t postShift); + + + /** + * @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q15( + const arm_biquad_casd_df1_inst_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 Biquad cascade filter + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_fast_q31( + const arm_biquad_casd_df1_inst_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 Biquad cascade filter. + * @param[in,out] S points to an instance of the Q31 Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cascade_df1_init_q31( + arm_biquad_casd_df1_inst_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q31_t * pState, + int8_t postShift); + + + /** + * @brief Processing function for the floating-point Biquad cascade filter. + * @param[in] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df1_f32( + const arm_biquad_casd_df1_inst_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point Biquad cascade filter. + * @param[in,out] S points to an instance of the floating-point Biquad cascade structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df1_init_f32( + arm_biquad_casd_df1_inst_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float32_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f32; + + + /** + * @brief Instance structure for the floating-point matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + float64_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_f64; + + /** + * @brief Instance structure for the Q15 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q15_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q15; + + /** + * @brief Instance structure for the Q31 matrix structure. + */ + typedef struct + { + uint16_t numRows; /**< number of rows of the matrix. */ + uint16_t numCols; /**< number of columns of the matrix. */ + q31_t *pData; /**< points to the data of the matrix. */ + } arm_matrix_instance_q31; + + + /** + * @brief Floating-point matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix addition. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_add_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pScratch); + + + /** + * @brief Q31, complex, matrix multiplication. + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_cmplx_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_f32( + const arm_matrix_instance_f32 * pSrc, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q15( + const arm_matrix_instance_q15 * pSrc, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix transpose. + * @param[in] pSrc points to the input matrix + * @param[out] pDst points to the output matrix + * @return The function returns either ARM_MATH_SIZE_MISMATCH + * or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_trans_q31( + const arm_matrix_instance_q31 * pSrc, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @param[in] pState points to the array for storing intermediate results + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst, + q15_t * pState); + + + /** + * @brief Q31 matrix multiplication + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_mult_fast_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_f32( + const arm_matrix_instance_f32 * pSrcA, + const arm_matrix_instance_f32 * pSrcB, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q15( + const arm_matrix_instance_q15 * pSrcA, + const arm_matrix_instance_q15 * pSrcB, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix subtraction + * @param[in] pSrcA points to the first input matrix structure + * @param[in] pSrcB points to the second input matrix structure + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_sub_q31( + const arm_matrix_instance_q31 * pSrcA, + const arm_matrix_instance_q31 * pSrcB, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Floating-point matrix scaling. + * @param[in] pSrc points to the input matrix + * @param[in] scale scale factor + * @param[out] pDst points to the output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_f32( + const arm_matrix_instance_f32 * pSrc, + float32_t scale, + arm_matrix_instance_f32 * pDst); + + + /** + * @brief Q15 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q15( + const arm_matrix_instance_q15 * pSrc, + q15_t scaleFract, + int32_t shift, + arm_matrix_instance_q15 * pDst); + + + /** + * @brief Q31 matrix scaling. + * @param[in] pSrc points to input matrix + * @param[in] scaleFract fractional portion of the scale factor + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to output matrix structure + * @return The function returns either + * ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking. + */ + arm_status arm_mat_scale_q31( + const arm_matrix_instance_q31 * pSrc, + q31_t scaleFract, + int32_t shift, + arm_matrix_instance_q31 * pDst); + + + /** + * @brief Q31 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q31( + arm_matrix_instance_q31 * S, + uint16_t nRows, + uint16_t nColumns, + q31_t * pData); + + + /** + * @brief Q15 matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_q15( + arm_matrix_instance_q15 * S, + uint16_t nRows, + uint16_t nColumns, + q15_t * pData); + + + /** + * @brief Floating-point matrix initialization. + * @param[in,out] S points to an instance of the floating-point matrix structure. + * @param[in] nRows number of rows in the matrix. + * @param[in] nColumns number of columns in the matrix. + * @param[in] pData points to the matrix data array. + */ + void arm_mat_init_f32( + arm_matrix_instance_f32 * S, + uint16_t nRows, + uint16_t nColumns, + float32_t * pData); + + + + /** + * @brief Instance structure for the Q15 PID Control. + */ + typedef struct + { + q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ +#if !defined (ARM_MATH_DSP) + q15_t A1; + q15_t A2; +#else + q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/ +#endif + q15_t state[3]; /**< The state array of length 3. */ + q15_t Kp; /**< The proportional gain. */ + q15_t Ki; /**< The integral gain. */ + q15_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q15; + + /** + * @brief Instance structure for the Q31 PID Control. + */ + typedef struct + { + q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + q31_t A2; /**< The derived gain, A2 = Kd . */ + q31_t state[3]; /**< The state array of length 3. */ + q31_t Kp; /**< The proportional gain. */ + q31_t Ki; /**< The integral gain. */ + q31_t Kd; /**< The derivative gain. */ + } arm_pid_instance_q31; + + /** + * @brief Instance structure for the floating-point PID Control. + */ + typedef struct + { + float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */ + float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */ + float32_t A2; /**< The derived gain, A2 = Kd . */ + float32_t state[3]; /**< The state array of length 3. */ + float32_t Kp; /**< The proportional gain. */ + float32_t Ki; /**< The integral gain. */ + float32_t Kd; /**< The derivative gain. */ + } arm_pid_instance_f32; + + + + /** + * @brief Initialization function for the floating-point PID Control. + * @param[in,out] S points to an instance of the PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_f32( + arm_pid_instance_f32 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + */ + void arm_pid_reset_f32( + arm_pid_instance_f32 * S); + + + /** + * @brief Initialization function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q31( + arm_pid_instance_q31 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + */ + + void arm_pid_reset_q31( + arm_pid_instance_q31 * S); + + + /** + * @brief Initialization function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID structure. + * @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state. + */ + void arm_pid_init_q15( + arm_pid_instance_q15 * S, + int32_t resetStateFlag); + + + /** + * @brief Reset function for the Q15 PID Control. + * @param[in,out] S points to an instance of the q15 PID Control structure + */ + void arm_pid_reset_q15( + arm_pid_instance_q15 * S); + + + /** + * @brief Instance structure for the floating-point Linear Interpolate function. + */ + typedef struct + { + uint32_t nValues; /**< nValues */ + float32_t x1; /**< x1 */ + float32_t xSpacing; /**< xSpacing */ + float32_t *pYData; /**< pointer to the table of Y values */ + } arm_linear_interp_instance_f32; + + /** + * @brief Instance structure for the floating-point bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + float32_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_f32; + + /** + * @brief Instance structure for the Q31 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q31_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q31; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q15_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q15; + + /** + * @brief Instance structure for the Q15 bilinear interpolation function. + */ + typedef struct + { + uint16_t numRows; /**< number of rows in the data table. */ + uint16_t numCols; /**< number of columns in the data table. */ + q7_t *pData; /**< points to the data table. */ + } arm_bilinear_interp_instance_q7; + + + /** + * @brief Q7 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector multiplication. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_mult_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q15( + arm_cfft_radix2_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q15( + const arm_cfft_radix2_instance_q15 * S, + q15_t * pSrc); + + + /** + * @brief Instance structure for the Q15 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q15; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q15( + arm_cfft_radix4_instance_q15 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_q15( + const arm_cfft_radix4_instance_q15 * S, + q15_t * pSrc); + + /** + * @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix2_instance_q31; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_q31( + arm_cfft_radix2_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_q31( + const arm_cfft_radix2_instance_q31 * S, + q31_t * pSrc); + + /** + * @brief Instance structure for the Q31 CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + } arm_cfft_radix4_instance_q31; + +/* Deprecated */ + void arm_cfft_radix4_q31( + const arm_cfft_radix4_instance_q31 * S, + q31_t * pSrc); + +/* Deprecated */ + arm_status arm_cfft_radix4_init_q31( + arm_cfft_radix4_instance_q31 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix2_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix2_init_f32( + arm_cfft_radix2_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix2_f32( + const arm_cfft_radix2_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */ + uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */ + float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */ + float32_t onebyfftLen; /**< value of 1/fftLen. */ + } arm_cfft_radix4_instance_f32; + +/* Deprecated */ + arm_status arm_cfft_radix4_init_f32( + arm_cfft_radix4_instance_f32 * S, + uint16_t fftLen, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + +/* Deprecated */ + void arm_cfft_radix4_f32( + const arm_cfft_radix4_instance_f32 * S, + float32_t * pSrc); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q15_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q15; + +void arm_cfft_q15( + const arm_cfft_instance_q15 * S, + q15_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the fixed-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const q31_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_q31; + +void arm_cfft_q31( + const arm_cfft_instance_q31 * S, + q31_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the floating-point CFFT/CIFFT function. + */ + typedef struct + { + uint16_t fftLen; /**< length of the FFT. */ + const float32_t *pTwiddle; /**< points to the Twiddle factor table. */ + const uint16_t *pBitRevTable; /**< points to the bit reversal table. */ + uint16_t bitRevLength; /**< bit reversal table length. */ + } arm_cfft_instance_f32; + + void arm_cfft_f32( + const arm_cfft_instance_f32 * S, + float32_t * p1, + uint8_t ifftFlag, + uint8_t bitReverseFlag); + + /** + * @brief Instance structure for the Q15 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q15; + + arm_status arm_rfft_init_q15( + arm_rfft_instance_q15 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q15( + const arm_rfft_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst); + + /** + * @brief Instance structure for the Q31 RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + const arm_cfft_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_q31; + + arm_status arm_rfft_init_q31( + arm_rfft_instance_q31 * S, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_q31( + const arm_rfft_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ + typedef struct + { + uint32_t fftLenReal; /**< length of the real FFT. */ + uint16_t fftLenBy2; /**< length of the complex FFT. */ + uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */ + uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */ + uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */ + float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */ + float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_rfft_instance_f32; + + arm_status arm_rfft_init_f32( + arm_rfft_instance_f32 * S, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint32_t fftLenReal, + uint32_t ifftFlagR, + uint32_t bitReverseFlag); + + void arm_rfft_f32( + const arm_rfft_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst); + + /** + * @brief Instance structure for the floating-point RFFT/RIFFT function. + */ +typedef struct + { + arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */ + uint16_t fftLenRFFT; /**< length of the real sequence */ + float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */ + } arm_rfft_fast_instance_f32 ; + +arm_status arm_rfft_fast_init_f32 ( + arm_rfft_fast_instance_f32 * S, + uint16_t fftLen); + +void arm_rfft_fast_f32( + arm_rfft_fast_instance_f32 * S, + float32_t * p, float32_t * pOut, + uint8_t ifftFlag); + + /** + * @brief Instance structure for the floating-point DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + float32_t normalize; /**< normalizing factor. */ + float32_t *pTwiddle; /**< points to the twiddle factor table. */ + float32_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_f32; + + + /** + * @brief Initialization function for the floating-point DCT4/IDCT4. + * @param[in,out] S points to an instance of floating-point DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of floating-point RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of floating-point CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length. + */ + arm_status arm_dct4_init_f32( + arm_dct4_instance_f32 * S, + arm_rfft_instance_f32 * S_RFFT, + arm_cfft_radix4_instance_f32 * S_CFFT, + uint16_t N, + uint16_t Nby2, + float32_t normalize); + + + /** + * @brief Processing function for the floating-point DCT4/IDCT4. + * @param[in] S points to an instance of the floating-point DCT4/IDCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_f32( + const arm_dct4_instance_f32 * S, + float32_t * pState, + float32_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q31 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q31_t normalize; /**< normalizing factor. */ + q31_t *pTwiddle; /**< points to the twiddle factor table. */ + q31_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q31; + + + /** + * @brief Initialization function for the Q31 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q31 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q31 RFFT/RIFFT structure + * @param[in] S_CFFT points to an instance of Q31 CFFT/CIFFT structure + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q31( + arm_dct4_instance_q31 * S, + arm_rfft_instance_q31 * S_RFFT, + arm_cfft_radix4_instance_q31 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q31_t normalize); + + + /** + * @brief Processing function for the Q31 DCT4/IDCT4. + * @param[in] S points to an instance of the Q31 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q31( + const arm_dct4_instance_q31 * S, + q31_t * pState, + q31_t * pInlineBuffer); + + + /** + * @brief Instance structure for the Q15 DCT4/IDCT4 function. + */ + typedef struct + { + uint16_t N; /**< length of the DCT4. */ + uint16_t Nby2; /**< half of the length of the DCT4. */ + q15_t normalize; /**< normalizing factor. */ + q15_t *pTwiddle; /**< points to the twiddle factor table. */ + q15_t *pCosFactor; /**< points to the cosFactor table. */ + arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */ + arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */ + } arm_dct4_instance_q15; + + + /** + * @brief Initialization function for the Q15 DCT4/IDCT4. + * @param[in,out] S points to an instance of Q15 DCT4/IDCT4 structure. + * @param[in] S_RFFT points to an instance of Q15 RFFT/RIFFT structure. + * @param[in] S_CFFT points to an instance of Q15 CFFT/CIFFT structure. + * @param[in] N length of the DCT4. + * @param[in] Nby2 half of the length of the DCT4. + * @param[in] normalize normalizing factor. + * @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length. + */ + arm_status arm_dct4_init_q15( + arm_dct4_instance_q15 * S, + arm_rfft_instance_q15 * S_RFFT, + arm_cfft_radix4_instance_q15 * S_CFFT, + uint16_t N, + uint16_t Nby2, + q15_t normalize); + + + /** + * @brief Processing function for the Q15 DCT4/IDCT4. + * @param[in] S points to an instance of the Q15 DCT4 structure. + * @param[in] pState points to state buffer. + * @param[in,out] pInlineBuffer points to the in-place input and output buffer. + */ + void arm_dct4_q15( + const arm_dct4_instance_q15 * S, + q15_t * pState, + q15_t * pInlineBuffer); + + + /** + * @brief Floating-point vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector addition. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_add_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q7( + q7_t * pSrcA, + q7_t * pSrcB, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector subtraction. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in each vector + */ + void arm_sub_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a floating-point vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scale scale factor to be applied + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_f32( + float32_t * pSrc, + float32_t scale, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q7 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q7( + q7_t * pSrc, + q7_t scaleFract, + int8_t shift, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q15 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q15( + q15_t * pSrc, + q15_t scaleFract, + int8_t shift, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Multiplies a Q31 vector by a scalar. + * @param[in] pSrc points to the input vector + * @param[in] scaleFract fractional portion of the scale value + * @param[in] shift number of bits to shift the result by + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_scale_q31( + q31_t * pSrc, + q31_t scaleFract, + int8_t shift, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q7 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Floating-point vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q15 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Q31 vector absolute value. + * @param[in] pSrc points to the input buffer + * @param[out] pDst points to the output buffer + * @param[in] blockSize number of samples in each vector + */ + void arm_abs_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Dot product of floating-point vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t blockSize, + float32_t * result); + + + /** + * @brief Dot product of Q7 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q7( + q7_t * pSrcA, + q7_t * pSrcB, + uint32_t blockSize, + q31_t * result); + + + /** + * @brief Dot product of Q15 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Dot product of Q31 vectors. + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] blockSize number of samples in each vector + * @param[out] result output result returned here + */ + void arm_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t blockSize, + q63_t * result); + + + /** + * @brief Shifts the elements of a Q7 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q7( + q7_t * pSrc, + int8_t shiftBits, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q15 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q15( + q15_t * pSrc, + int8_t shiftBits, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Shifts the elements of a Q31 vector a specified number of bits. + * @param[in] pSrc points to the input vector + * @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right. + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_shift_q31( + q31_t * pSrc, + int8_t shiftBits, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_f32( + float32_t * pSrc, + float32_t offset, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q7( + q7_t * pSrc, + q7_t offset, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q15( + q15_t * pSrc, + q15_t offset, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Adds a constant offset to a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[in] offset is the offset to be added + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_offset_q31( + q31_t * pSrc, + q31_t offset, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a floating-point vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q7 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q15 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Negates the elements of a Q31 vector. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] blockSize number of samples in the vector + */ + void arm_negate_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a floating-point vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q7 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q7( + q7_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Copies the elements of a Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_copy_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a floating-point vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_f32( + float32_t value, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q7 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q7( + q7_t value, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q15 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q15( + q15_t value, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Fills a constant value into a Q31 vector. + * @param[in] value input value to be filled + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_fill_q31( + q31_t value, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the location where the output result is written. Length srcALen+srcBLen-1. + */ + void arm_conv_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + */ + void arm_conv_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_conv_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length srcALen+srcBLen-1. + */ + void arm_conv_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Partial convolution of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Partial convolution of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Partial convolution of Q7 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints, + q15_t * pScratch1, + q15_t * pScratch2); + + +/** + * @brief Partial convolution of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data + * @param[in] firstIndex is the first output sample to start with. + * @param[in] numPoints is the number of output points to be computed. + * @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2]. + */ + arm_status arm_conv_partial_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + uint32_t firstIndex, + uint32_t numPoints); + + + /** + * @brief Instance structure for the Q15 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR decimator. + */ + typedef struct + { + uint8_t M; /**< decimation factor. */ + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + } arm_fir_decimate_instance_f32; + + + /** + * @brief Processing function for the floating-point FIR decimator. + * @param[in] S points to an instance of the floating-point FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_f32( + const arm_fir_decimate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR decimator. + * @param[in,out] S points to an instance of the floating-point FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_f32( + arm_fir_decimate_instance_f32 * S, + uint16_t numTaps, + uint8_t M, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q15 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q15( + const arm_fir_decimate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR decimator. + * @param[in,out] S points to an instance of the Q15 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q15( + arm_fir_decimate_instance_q15 * S, + uint16_t numTaps, + uint8_t M, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR decimator. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_q31( + const arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + /** + * @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4. + * @param[in] S points to an instance of the Q31 FIR decimator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_decimate_fast_q31( + arm_fir_decimate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR decimator. + * @param[in,out] S points to an instance of the Q31 FIR decimator structure. + * @param[in] numTaps number of coefficients in the filter. + * @param[in] M decimation factor. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * blockSize is not a multiple of M. + */ + arm_status arm_fir_decimate_init_q31( + arm_fir_decimate_instance_q31 * S, + uint16_t numTaps, + uint8_t M, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */ + } arm_fir_interpolate_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR interpolator. + */ + typedef struct + { + uint8_t L; /**< upsample factor. */ + uint16_t phaseLength; /**< length of each polyphase filter component. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */ + float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */ + } arm_fir_interpolate_instance_f32; + + + /** + * @brief Processing function for the Q15 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q15( + const arm_fir_interpolate_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 FIR interpolator. + * @param[in,out] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q15( + arm_fir_interpolate_instance_q15 * S, + uint8_t L, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 FIR interpolator. + * @param[in] S points to an instance of the Q15 FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_q31( + const arm_fir_interpolate_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR interpolator. + * @param[in,out] S points to an instance of the Q31 FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_q31( + arm_fir_interpolate_instance_q31 * S, + uint8_t L, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point FIR interpolator. + * @param[in] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_interpolate_f32( + const arm_fir_interpolate_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point FIR interpolator. + * @param[in,out] S points to an instance of the floating-point FIR interpolator structure. + * @param[in] L upsample factor. + * @param[in] numTaps number of filter coefficients in the filter. + * @param[in] pCoeffs points to the filter coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] blockSize number of input samples to process per call. + * @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if + * the filter length numTaps is not a multiple of the interpolation factor L. + */ + arm_status arm_fir_interpolate_init_f32( + arm_fir_interpolate_instance_f32 * S, + uint8_t L, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the high precision Q31 Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */ + } arm_biquad_cas_df1_32x64_ins_q31; + + + /** + * @param[in] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cas_df1_32x64_q31( + const arm_biquad_cas_df1_32x64_ins_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @param[in,out] S points to an instance of the high precision Q31 Biquad cascade filter structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] postShift shift to be applied to the output. Varies according to the coefficients format + */ + void arm_biquad_cas_df1_32x64_init_q31( + arm_biquad_cas_df1_32x64_ins_q31 * S, + uint8_t numStages, + q31_t * pCoeffs, + q63_t * pState, + uint8_t postShift); + + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float32_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */ + float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_stereo_df2T_instance_f32; + + /** + * @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter. + */ + typedef struct + { + uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */ + float64_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */ + float64_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */ + } arm_biquad_cascade_df2T_instance_f64; + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f32( + const arm_biquad_cascade_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_stereo_df2T_f32( + const arm_biquad_cascade_stereo_df2T_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in] S points to an instance of the filter data structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_biquad_cascade_df2T_f64( + const arm_biquad_cascade_df2T_instance_f64 * S, + float64_t * pSrc, + float64_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f32( + arm_biquad_cascade_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_stereo_df2T_init_f32( + arm_biquad_cascade_stereo_df2T_instance_f32 * S, + uint8_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter. + * @param[in,out] S points to an instance of the filter data structure. + * @param[in] numStages number of 2nd order stages in the filter. + * @param[in] pCoeffs points to the filter coefficients. + * @param[in] pState points to the state buffer. + */ + void arm_biquad_cascade_df2T_init_f64( + arm_biquad_cascade_df2T_instance_f64 * S, + uint8_t numStages, + float64_t * pCoeffs, + float64_t * pState); + + + /** + * @brief Instance structure for the Q15 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point FIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of filter stages. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */ + } arm_fir_lattice_instance_f32; + + + /** + * @brief Initialization function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q15( + arm_fir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pCoeffs, + q15_t * pState); + + + /** + * @brief Processing function for the Q15 FIR lattice filter. + * @param[in] S points to an instance of the Q15 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q15( + const arm_fir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_q31( + arm_fir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pCoeffs, + q31_t * pState); + + + /** + * @brief Processing function for the Q31 FIR lattice filter. + * @param[in] S points to an instance of the Q31 FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_q31( + const arm_fir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] numStages number of filter stages. + * @param[in] pCoeffs points to the coefficient buffer. The array is of length numStages. + * @param[in] pState points to the state buffer. The array is of length numStages. + */ + void arm_fir_lattice_init_f32( + arm_fir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pCoeffs, + float32_t * pState); + + + /** + * @brief Processing function for the floating-point FIR lattice filter. + * @param[in] S points to an instance of the floating-point FIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] blockSize number of samples to process. + */ + void arm_fir_lattice_f32( + const arm_fir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q15; + + /** + * @brief Instance structure for the Q31 IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_q31; + + /** + * @brief Instance structure for the floating-point IIR lattice filter. + */ + typedef struct + { + uint16_t numStages; /**< number of stages in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */ + float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */ + float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */ + } arm_iir_lattice_instance_f32; + + + /** + * @brief Processing function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_f32( + const arm_iir_lattice_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point IIR lattice filter. + * @param[in] S points to an instance of the floating-point IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize-1. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_f32( + arm_iir_lattice_instance_f32 * S, + uint16_t numStages, + float32_t * pkCoeffs, + float32_t * pvCoeffs, + float32_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q31( + const arm_iir_lattice_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 IIR lattice filter. + * @param[in] S points to an instance of the Q31 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to the reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to the state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_init_q31( + arm_iir_lattice_instance_q31 * S, + uint16_t numStages, + q31_t * pkCoeffs, + q31_t * pvCoeffs, + q31_t * pState, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the Q15 IIR lattice structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data. + * @param[in] blockSize number of samples to process. + */ + void arm_iir_lattice_q15( + const arm_iir_lattice_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + +/** + * @brief Initialization function for the Q15 IIR lattice filter. + * @param[in] S points to an instance of the fixed-point Q15 IIR lattice structure. + * @param[in] numStages number of stages in the filter. + * @param[in] pkCoeffs points to reflection coefficient buffer. The array is of length numStages. + * @param[in] pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1. + * @param[in] pState points to state buffer. The array is of length numStages+blockSize. + * @param[in] blockSize number of samples to process per call. + */ + void arm_iir_lattice_init_q15( + arm_iir_lattice_instance_q15 * S, + uint16_t numStages, + q15_t * pkCoeffs, + q15_t * pvCoeffs, + q15_t * pState, + uint32_t blockSize); + + + /** + * @brief Instance structure for the floating-point LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that controls filter coefficient updates. */ + } arm_lms_instance_f32; + + + /** + * @brief Processing function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_f32( + const arm_lms_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_init_f32( + arm_lms_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q15 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q15; + + + /** + * @brief Initialization function for the Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to the coefficient buffer. + * @param[in] pState points to the state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q15( + arm_lms_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Processing function for Q15 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q15( + const arm_lms_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint32_t postShift; /**< bit shift applied to coefficients. */ + } arm_lms_instance_q31; + + + /** + * @brief Processing function for Q31 LMS filter. + * @param[in] S points to an instance of the Q15 LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_q31( + const arm_lms_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 LMS filter. + * @param[in] S points to an instance of the Q31 LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_init_q31( + arm_lms_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint32_t postShift); + + + /** + * @brief Instance structure for the floating-point normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + float32_t mu; /**< step size that control filter coefficient updates. */ + float32_t energy; /**< saves previous frame energy. */ + float32_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_f32; + + + /** + * @brief Processing function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_f32( + arm_lms_norm_instance_f32 * S, + float32_t * pSrc, + float32_t * pRef, + float32_t * pOut, + float32_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for floating-point normalized LMS filter. + * @param[in] S points to an instance of the floating-point LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_init_f32( + arm_lms_norm_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + float32_t mu, + uint32_t blockSize); + + + /** + * @brief Instance structure for the Q31 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q31_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q31_t *recipTable; /**< points to the reciprocal initial value table. */ + q31_t energy; /**< saves previous frame energy. */ + q31_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q31; + + + /** + * @brief Processing function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q31( + arm_lms_norm_instance_q31 * S, + q31_t * pSrc, + q31_t * pRef, + q31_t * pOut, + q31_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q31 normalized LMS filter. + * @param[in] S points to an instance of the Q31 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q31( + arm_lms_norm_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + q31_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Instance structure for the Q15 normalized LMS filter. + */ + typedef struct + { + uint16_t numTaps; /**< Number of coefficients in the filter. */ + q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */ + q15_t mu; /**< step size that controls filter coefficient updates. */ + uint8_t postShift; /**< bit shift applied to coefficients. */ + q15_t *recipTable; /**< Points to the reciprocal initial value table. */ + q15_t energy; /**< saves previous frame energy. */ + q15_t x0; /**< saves previous input sample. */ + } arm_lms_norm_instance_q15; + + + /** + * @brief Processing function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] pSrc points to the block of input data. + * @param[in] pRef points to the block of reference data. + * @param[out] pOut points to the block of output data. + * @param[out] pErr points to the block of error data. + * @param[in] blockSize number of samples to process. + */ + void arm_lms_norm_q15( + arm_lms_norm_instance_q15 * S, + q15_t * pSrc, + q15_t * pRef, + q15_t * pOut, + q15_t * pErr, + uint32_t blockSize); + + + /** + * @brief Initialization function for Q15 normalized LMS filter. + * @param[in] S points to an instance of the Q15 normalized LMS filter structure. + * @param[in] numTaps number of filter coefficients. + * @param[in] pCoeffs points to coefficient buffer. + * @param[in] pState points to state buffer. + * @param[in] mu step size that controls filter coefficient updates. + * @param[in] blockSize number of samples to process. + * @param[in] postShift bit shift applied to coefficients. + */ + void arm_lms_norm_init_q15( + arm_lms_norm_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + q15_t mu, + uint32_t blockSize, + uint8_t postShift); + + + /** + * @brief Correlation of floating-point sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_f32( + float32_t * pSrcA, + uint32_t srcALen, + float32_t * pSrcB, + uint32_t srcBLen, + float32_t * pDst); + + + /** + * @brief Correlation of Q15 sequences + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q15 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + + void arm_correlate_fast_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst); + + + /** + * @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + */ + void arm_correlate_fast_opt_q15( + q15_t * pSrcA, + uint32_t srcALen, + q15_t * pSrcB, + uint32_t srcBLen, + q15_t * pDst, + q15_t * pScratch); + + + /** + * @brief Correlation of Q31 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4 + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_fast_q31( + q31_t * pSrcA, + uint32_t srcALen, + q31_t * pSrcB, + uint32_t srcBLen, + q31_t * pDst); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + * @param[in] pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2. + * @param[in] pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen). + */ + void arm_correlate_opt_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst, + q15_t * pScratch1, + q15_t * pScratch2); + + + /** + * @brief Correlation of Q7 sequences. + * @param[in] pSrcA points to the first input sequence. + * @param[in] srcALen length of the first input sequence. + * @param[in] pSrcB points to the second input sequence. + * @param[in] srcBLen length of the second input sequence. + * @param[out] pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1. + */ + void arm_correlate_q7( + q7_t * pSrcA, + uint32_t srcALen, + q7_t * pSrcB, + uint32_t srcBLen, + q7_t * pDst); + + + /** + * @brief Instance structure for the floating-point sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_f32; + + /** + * @brief Instance structure for the Q31 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q31; + + /** + * @brief Instance structure for the Q15 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q15; + + /** + * @brief Instance structure for the Q7 sparse FIR filter. + */ + typedef struct + { + uint16_t numTaps; /**< number of coefficients in the filter. */ + uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */ + q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */ + q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/ + uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */ + int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */ + } arm_fir_sparse_instance_q7; + + + /** + * @brief Processing function for the floating-point sparse FIR filter. + * @param[in] S points to an instance of the floating-point sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_f32( + arm_fir_sparse_instance_f32 * S, + float32_t * pSrc, + float32_t * pDst, + float32_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the floating-point sparse FIR filter. + * @param[in,out] S points to an instance of the floating-point sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_f32( + arm_fir_sparse_instance_f32 * S, + uint16_t numTaps, + float32_t * pCoeffs, + float32_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q31 sparse FIR filter. + * @param[in] S points to an instance of the Q31 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q31( + arm_fir_sparse_instance_q31 * S, + q31_t * pSrc, + q31_t * pDst, + q31_t * pScratchIn, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q31 sparse FIR filter. + * @param[in,out] S points to an instance of the Q31 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q31( + arm_fir_sparse_instance_q31 * S, + uint16_t numTaps, + q31_t * pCoeffs, + q31_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q15 sparse FIR filter. + * @param[in] S points to an instance of the Q15 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q15( + arm_fir_sparse_instance_q15 * S, + q15_t * pSrc, + q15_t * pDst, + q15_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q15 sparse FIR filter. + * @param[in,out] S points to an instance of the Q15 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q15( + arm_fir_sparse_instance_q15 * S, + uint16_t numTaps, + q15_t * pCoeffs, + q15_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Processing function for the Q7 sparse FIR filter. + * @param[in] S points to an instance of the Q7 sparse FIR structure. + * @param[in] pSrc points to the block of input data. + * @param[out] pDst points to the block of output data + * @param[in] pScratchIn points to a temporary buffer of size blockSize. + * @param[in] pScratchOut points to a temporary buffer of size blockSize. + * @param[in] blockSize number of input samples to process per call. + */ + void arm_fir_sparse_q7( + arm_fir_sparse_instance_q7 * S, + q7_t * pSrc, + q7_t * pDst, + q7_t * pScratchIn, + q31_t * pScratchOut, + uint32_t blockSize); + + + /** + * @brief Initialization function for the Q7 sparse FIR filter. + * @param[in,out] S points to an instance of the Q7 sparse FIR structure. + * @param[in] numTaps number of nonzero coefficients in the filter. + * @param[in] pCoeffs points to the array of filter coefficients. + * @param[in] pState points to the state buffer. + * @param[in] pTapDelay points to the array of offset times. + * @param[in] maxDelay maximum offset time supported. + * @param[in] blockSize number of samples that will be processed per block. + */ + void arm_fir_sparse_init_q7( + arm_fir_sparse_instance_q7 * S, + uint16_t numTaps, + q7_t * pCoeffs, + q7_t * pState, + int32_t * pTapDelay, + uint16_t maxDelay, + uint32_t blockSize); + + + /** + * @brief Floating-point sin_cos function. + * @param[in] theta input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cos output. + */ + void arm_sin_cos_f32( + float32_t theta, + float32_t * pSinVal, + float32_t * pCosVal); + + + /** + * @brief Q31 sin_cos function. + * @param[in] theta scaled input value in degrees + * @param[out] pSinVal points to the processed sine output. + * @param[out] pCosVal points to the processed cosine output. + */ + void arm_sin_cos_q31( + q31_t theta, + q31_t * pSinVal, + q31_t * pCosVal); + + + /** + * @brief Floating-point complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + /** + * @brief Q31 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex conjugate. + * @param[in] pSrc points to the input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_conj_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude squared + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_squared_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup PID PID Motor Control + * + * A Proportional Integral Derivative (PID) controller is a generic feedback control + * loop mechanism widely used in industrial control systems. + * A PID controller is the most commonly used type of feedback controller. + * + * This set of functions implements (PID) controllers + * for Q15, Q31, and floating-point data types. The functions operate on a single sample + * of data and each call to the function returns a single processed value. + * S points to an instance of the PID control data structure. in + * is the input sample value. The functions return the output value. + * + * \par Algorithm: + *
+   *    y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2]
+   *    A0 = Kp + Ki + Kd
+   *    A1 = (-Kp ) - (2 * Kd )
+   *    A2 = Kd  
+ * + * \par + * where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant + * + * \par + * \image html PID.gif "Proportional Integral Derivative Controller" + * + * \par + * The PID controller calculates an "error" value as the difference between + * the measured output and the reference input. + * The controller attempts to minimize the error by adjusting the process control inputs. + * The proportional value determines the reaction to the current error, + * the integral value determines the reaction based on the sum of recent errors, + * and the derivative value determines the reaction based on the rate at which the error has been changing. + * + * \par Instance Structure + * The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure. + * A separate instance structure must be defined for each PID Controller. + * There are separate instance structure declarations for each of the 3 supported data types. + * + * \par Reset Functions + * There is also an associated reset function for each data type which clears the state array. + * + * \par Initialization Functions + * There is also an associated initialization function for each data type. + * The initialization function performs the following operations: + * - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains. + * - Zeros out the values in the state buffer. + * + * \par + * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function. + * + * \par Fixed-Point Behavior + * Care must be taken when using the fixed-point versions of the PID Controller functions. + * In particular, the overflow and saturation behavior of the accumulator used in each function must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup PID + * @{ + */ + + /** + * @brief Process function for the floating-point PID Control. + * @param[in,out] S is an instance of the floating-point PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + */ + CMSIS_INLINE __STATIC_INLINE float32_t arm_pid_f32( + arm_pid_instance_f32 * S, + float32_t in) + { + float32_t out; + + /* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */ + out = (S->A0 * in) + + (S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + + } + + /** + * @brief Process function for the Q31 PID Control. + * @param[in,out] S points to an instance of the Q31 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 64-bit accumulator. + * The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit. + * Thus, if the accumulator result overflows it wraps around rather than clip. + * In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions. + * After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format. + */ + CMSIS_INLINE __STATIC_INLINE q31_t arm_pid_q31( + arm_pid_instance_q31 * S, + q31_t in) + { + q63_t acc; + q31_t out; + + /* acc = A0 * x[n] */ + acc = (q63_t) S->A0 * in; + + /* acc += A1 * x[n-1] */ + acc += (q63_t) S->A1 * S->state[0]; + + /* acc += A2 * x[n-2] */ + acc += (q63_t) S->A2 * S->state[1]; + + /* convert output to 1.31 format to add y[n-1] */ + out = (q31_t) (acc >> 31U); + + /* out += y[n-1] */ + out += S->state[2]; + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + + /** + * @brief Process function for the Q15 PID Control. + * @param[in,out] S points to an instance of the Q15 PID Control structure + * @param[in] in input sample to process + * @return out processed output sample. + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using a 64-bit internal accumulator. + * Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result. + * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format. + * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved. + * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits. + * Lastly, the accumulator is saturated to yield a result in 1.15 format. + */ + CMSIS_INLINE __STATIC_INLINE q15_t arm_pid_q15( + arm_pid_instance_q15 * S, + q15_t in) + { + q63_t acc; + q15_t out; + +#if defined (ARM_MATH_DSP) + __SIMD32_TYPE *vstate; + + /* Implementation of PID controller */ + + /* acc = A0 * x[n] */ + acc = (q31_t) __SMUAD((uint32_t)S->A0, (uint32_t)in); + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + vstate = __SIMD32_CONST(S->state); + acc = (q63_t)__SMLALD((uint32_t)S->A1, (uint32_t)*vstate, (uint64_t)acc); +#else + /* acc = A0 * x[n] */ + acc = ((q31_t) S->A0) * in; + + /* acc += A1 * x[n-1] + A2 * x[n-2] */ + acc += (q31_t) S->A1 * S->state[0]; + acc += (q31_t) S->A2 * S->state[1]; +#endif + + /* acc += y[n-1] */ + acc += (q31_t) S->state[2] << 15; + + /* saturate the output */ + out = (q15_t) (__SSAT((acc >> 15), 16)); + + /* Update state */ + S->state[1] = S->state[0]; + S->state[0] = in; + S->state[2] = out; + + /* return to application */ + return (out); + } + + /** + * @} end of PID group + */ + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f32( + const arm_matrix_instance_f32 * src, + arm_matrix_instance_f32 * dst); + + + /** + * @brief Floating-point matrix inverse. + * @param[in] src points to the instance of the input floating-point matrix structure. + * @param[out] dst points to the instance of the output floating-point matrix structure. + * @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match. + * If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR. + */ + arm_status arm_mat_inverse_f64( + const arm_matrix_instance_f64 * src, + arm_matrix_instance_f64 * dst); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup clarke Vector Clarke Transform + * Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector. + * Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents + * in the two-phase orthogonal stator axis Ialpha and Ibeta. + * When Ialpha is superposed with Ia as shown in the figure below + * \image html clarke.gif Stator current space vector and its components in (a,b). + * and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta + * can be calculated using only Ia and Ib. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeFormula.gif + * where Ia and Ib are the instantaneous stator phases and + * pIalpha and pIbeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup clarke + * @{ + */ + + /** + * + * @brief Floating-point Clarke transform + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + */ + CMSIS_INLINE __STATIC_INLINE void arm_clarke_f32( + float32_t Ia, + float32_t Ib, + float32_t * pIalpha, + float32_t * pIbeta) + { + /* Calculate pIalpha using the equation, pIalpha = Ia */ + *pIalpha = Ia; + + /* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */ + *pIbeta = ((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib); + } + + + /** + * @brief Clarke transform for Q31 version + * @param[in] Ia input three-phase coordinate a + * @param[in] Ib input three-phase coordinate b + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_clarke_q31( + q31_t Ia, + q31_t Ib, + q31_t * pIalpha, + q31_t * pIbeta) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIalpha from Ia by equation pIalpha = Ia */ + *pIalpha = Ia; + + /* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30); + + /* Intermediate product is calculated by (2/sqrt(3) * Ib) */ + product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30); + + /* pIbeta is calculated by adding the intermediate products */ + *pIbeta = __QADD(product1, product2); + } + + /** + * @} end of clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q31 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q31( + q7_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_clarke Vector Inverse Clarke Transform + * Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html clarkeInvFormula.gif + * where pIa and pIb are the instantaneous stator phases and + * Ialpha and Ibeta are the two coordinates of time invariant vector. + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Clarke transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_clarke + * @{ + */ + + /** + * @brief Floating-point Inverse Clarke transform + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pIa, + float32_t * pIb) + { + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */ + *pIb = -0.5f * Ialpha + 0.8660254039f * Ibeta; + } + + + /** + * @brief Inverse Clarke transform for Q31 version + * @param[in] Ialpha input two-phase orthogonal vector axis alpha + * @param[in] Ibeta input two-phase orthogonal vector axis beta + * @param[out] pIa points to output three-phase coordinate a + * @param[out] pIb points to output three-phase coordinate b + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the subtraction, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_clarke_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pIa, + q31_t * pIb) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + + /* Calculating pIa from Ialpha by equation pIa = Ialpha */ + *pIa = Ialpha; + + /* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31); + + /* Intermediate product is calculated by (1/sqrt(3) * pIb) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31); + + /* pIb is calculated by subtracting the products */ + *pIb = __QSUB(product2, product1); + } + + /** + * @} end of inv_clarke group + */ + + /** + * @brief Converts the elements of the Q7 vector to Q15 vector. + * @param[in] pSrc input pointer + * @param[out] pDst output pointer + * @param[in] blockSize number of samples to process + */ + void arm_q7_to_q15( + q7_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + + /** + * @ingroup groupController + */ + + /** + * @defgroup park Vector Park Transform + * + * Forward Park transform converts the input two-coordinate vector to flux and torque components. + * The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents + * from the stationary to the moving reference frame and control the spatial relationship between + * the stator vector current and rotor flux vector. + * If we consider the d axis aligned with the rotor flux, the diagram below shows the + * current vector and the relationship from the two reference frames: + * \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame" + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkFormula.gif + * where Ialpha and Ibeta are the stator vector components, + * pId and pIq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup park + * @{ + */ + + /** + * @brief Floating-point Park transform + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * The function implements the forward Park transform. + * + */ + CMSIS_INLINE __STATIC_INLINE void arm_park_f32( + float32_t Ialpha, + float32_t Ibeta, + float32_t * pId, + float32_t * pIq, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */ + *pId = Ialpha * cosVal + Ibeta * sinVal; + + /* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */ + *pIq = -Ialpha * sinVal + Ibeta * cosVal; + } + + + /** + * @brief Park transform for Q31 version + * @param[in] Ialpha input two-phase vector coordinate alpha + * @param[in] Ibeta input two-phase vector coordinate beta + * @param[out] pId points to output rotor reference frame d + * @param[out] pIq points to output rotor reference frame q + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition and subtraction, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_park_q31( + q31_t Ialpha, + q31_t Ibeta, + q31_t * pId, + q31_t * pIq, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Ialpha * cosVal) */ + product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * sinVal) */ + product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Ialpha * sinVal) */ + product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Ibeta * cosVal) */ + product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31); + + /* Calculate pId by adding the two intermediate products 1 and 2 */ + *pId = __QADD(product1, product2); + + /* Calculate pIq by subtracting the two intermediate products 3 from 4 */ + *pIq = __QSUB(product4, product3); + } + + /** + * @} end of park group + */ + + /** + * @brief Converts the elements of the Q7 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q7_to_float( + q7_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupController + */ + + /** + * @defgroup inv_park Vector Inverse Park transform + * Inverse Park transform converts the input flux and torque components to two-coordinate vector. + * + * The function operates on a single sample of data and each call to the function returns the processed output. + * The library provides separate functions for Q31 and floating-point data types. + * \par Algorithm + * \image html parkInvFormula.gif + * where pIalpha and pIbeta are the stator vector components, + * Id and Iq are rotor vector components and cosVal and sinVal are the + * cosine and sine values of theta (rotor flux position). + * \par Fixed-Point Behavior + * Care must be taken when using the Q31 version of the Park transform. + * In particular, the overflow and saturation behavior of the accumulator used must be considered. + * Refer to the function specific documentation below for usage guidelines. + */ + + /** + * @addtogroup inv_park + * @{ + */ + + /** + * @brief Floating-point Inverse Park transform + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_park_f32( + float32_t Id, + float32_t Iq, + float32_t * pIalpha, + float32_t * pIbeta, + float32_t sinVal, + float32_t cosVal) + { + /* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */ + *pIalpha = Id * cosVal - Iq * sinVal; + + /* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */ + *pIbeta = Id * sinVal + Iq * cosVal; + } + + + /** + * @brief Inverse Park transform for Q31 version + * @param[in] Id input coordinate of rotor reference frame d + * @param[in] Iq input coordinate of rotor reference frame q + * @param[out] pIalpha points to output two-phase orthogonal vector axis alpha + * @param[out] pIbeta points to output two-phase orthogonal vector axis beta + * @param[in] sinVal sine value of rotation angle theta + * @param[in] cosVal cosine value of rotation angle theta + * + * Scaling and Overflow Behavior: + * \par + * The function is implemented using an internal 32-bit accumulator. + * The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format. + * There is saturation on the addition, hence there is no risk of overflow. + */ + CMSIS_INLINE __STATIC_INLINE void arm_inv_park_q31( + q31_t Id, + q31_t Iq, + q31_t * pIalpha, + q31_t * pIbeta, + q31_t sinVal, + q31_t cosVal) + { + q31_t product1, product2; /* Temporary variables used to store intermediate results */ + q31_t product3, product4; /* Temporary variables used to store intermediate results */ + + /* Intermediate product is calculated by (Id * cosVal) */ + product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31); + + /* Intermediate product is calculated by (Iq * sinVal) */ + product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31); + + + /* Intermediate product is calculated by (Id * sinVal) */ + product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31); + + /* Intermediate product is calculated by (Iq * cosVal) */ + product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31); + + /* Calculate pIalpha by using the two intermediate products 1 and 2 */ + *pIalpha = __QSUB(product1, product2); + + /* Calculate pIbeta by using the two intermediate products 3 and 4 */ + *pIbeta = __QADD(product4, product3); + } + + /** + * @} end of Inverse park group + */ + + + /** + * @brief Converts the elements of the Q31 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_float( + q31_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup LinearInterpolate Linear Interpolation + * + * Linear interpolation is a method of curve fitting using linear polynomials. + * Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line + * + * \par + * \image html LinearInterp.gif "Linear interpolation" + * + * \par + * A Linear Interpolate function calculates an output value(y), for the input(x) + * using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values) + * + * \par Algorithm: + *
+   *       y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
+   *       where x0, x1 are nearest values of input x
+   *             y0, y1 are nearest values to output y
+   * 
+ * + * \par + * This set of functions implements Linear interpolation process + * for Q7, Q15, Q31, and floating-point data types. The functions operate on a single + * sample of data and each call to the function returns a single processed value. + * S points to an instance of the Linear Interpolate function data structure. + * x is the input sample value. The functions returns the output value. + * + * \par + * if x is outside of the table boundary, Linear interpolation returns first value of the table + * if x is below input range and returns last value of table if x is above range. + */ + + /** + * @addtogroup LinearInterpolate + * @{ + */ + + /** + * @brief Process function for the floating-point Linear Interpolation Function. + * @param[in,out] S is an instance of the floating-point Linear Interpolation structure + * @param[in] x input sample to process + * @return y processed output sample. + * + */ + CMSIS_INLINE __STATIC_INLINE float32_t arm_linear_interp_f32( + arm_linear_interp_instance_f32 * S, + float32_t x) + { + float32_t y; + float32_t x0, x1; /* Nearest input values */ + float32_t y0, y1; /* Nearest output values */ + float32_t xSpacing = S->xSpacing; /* spacing between input values */ + int32_t i; /* Index variable */ + float32_t *pYData = S->pYData; /* pointer to output table */ + + /* Calculation of index */ + i = (int32_t) ((x - S->x1) / xSpacing); + + if (i < 0) + { + /* Iniatilize output for below specified range as least output value of table */ + y = pYData[0]; + } + else if ((uint32_t)i >= S->nValues) + { + /* Iniatilize output for above specified range as last output value of table */ + y = pYData[S->nValues - 1]; + } + else + { + /* Calculation of nearest input values */ + x0 = S->x1 + i * xSpacing; + x1 = S->x1 + (i + 1) * xSpacing; + + /* Read of nearest output values */ + y0 = pYData[i]; + y1 = pYData[i + 1]; + + /* Calculation of output */ + y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0)); + + } + + /* returns output value */ + return (y); + } + + + /** + * + * @brief Process function for the Q31 Linear Interpolation Function. + * @param[in] pYData pointer to Q31 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + CMSIS_INLINE __STATIC_INLINE q31_t arm_linear_interp_q31( + q31_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q31_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (q31_t)0xFFF00000) >> 20); + + if (index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if (index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* shift left by 11 to keep fract in 1.31 format */ + fract = (x & 0x000FFFFF) << 11; + + /* Read two nearest output values from the index in 1.31(q31) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 2.30 format */ + y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32)); + + /* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */ + y += ((q31_t) (((q63_t) y1 * fract) >> 32)); + + /* Convert y to 1.31 format */ + return (y << 1U); + } + } + + + /** + * + * @brief Process function for the Q15 Linear Interpolation Function. + * @param[in] pYData pointer to Q15 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + * + */ + CMSIS_INLINE __STATIC_INLINE q15_t arm_linear_interp_q15( + q15_t * pYData, + q31_t x, + uint32_t nValues) + { + q63_t y; /* output */ + q15_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + int32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + index = ((x & (int32_t)0xFFF00000) >> 20); + + if (index >= (int32_t)(nValues - 1)) + { + return (pYData[nValues - 1]); + } + else if (index < 0) + { + return (pYData[0]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract) and y is in 13.35 format */ + y = ((q63_t) y0 * (0xFFFFF - fract)); + + /* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */ + y += ((q63_t) y1 * (fract)); + + /* convert y to 1.15 format */ + return (q15_t) (y >> 20); + } + } + + + /** + * + * @brief Process function for the Q7 Linear Interpolation Function. + * @param[in] pYData pointer to Q7 Linear Interpolation table + * @param[in] x input sample to process + * @param[in] nValues number of table values + * @return y processed output sample. + * + * \par + * Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part. + * This function can support maximum of table size 2^12. + */ + CMSIS_INLINE __STATIC_INLINE q7_t arm_linear_interp_q7( + q7_t * pYData, + q31_t x, + uint32_t nValues) + { + q31_t y; /* output */ + q7_t y0, y1; /* Nearest output values */ + q31_t fract; /* fractional part */ + uint32_t index; /* Index to read nearest output values */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + if (x < 0) + { + return (pYData[0]); + } + index = (x >> 20) & 0xfff; + + if (index >= (nValues - 1)) + { + return (pYData[nValues - 1]); + } + else + { + /* 20 bits for the fractional part */ + /* fract is in 12.20 format */ + fract = (x & 0x000FFFFF); + + /* Read two nearest output values from the index and are in 1.7(q7) format */ + y0 = pYData[index]; + y1 = pYData[index + 1]; + + /* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */ + y = ((y0 * (0xFFFFF - fract))); + + /* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */ + y += (y1 * fract); + + /* convert y to 1.7(q7) format */ + return (q7_t) (y >> 20); + } + } + + /** + * @} end of LinearInterpolate group + */ + + /** + * @brief Fast approximation to the trigonometric sine function for floating-point data. + * @param[in] x input value in radians. + * @return sin(x). + */ + float32_t arm_sin_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q31_t arm_sin_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric sine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return sin(x). + */ + q15_t arm_sin_q15( + q15_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for floating-point data. + * @param[in] x input value in radians. + * @return cos(x). + */ + float32_t arm_cos_f32( + float32_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q31 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q31_t arm_cos_q31( + q31_t x); + + + /** + * @brief Fast approximation to the trigonometric cosine function for Q15 data. + * @param[in] x Scaled input value in radians. + * @return cos(x). + */ + q15_t arm_cos_q15( + q15_t x); + + + /** + * @ingroup groupFastMath + */ + + + /** + * @defgroup SQRT Square Root + * + * Computes the square root of a number. + * There are separate functions for Q15, Q31, and floating-point data types. + * The square root function is computed using the Newton-Raphson algorithm. + * This is an iterative algorithm of the form: + *
+   *      x1 = x0 - f(x0)/f'(x0)
+   * 
+ * where x1 is the current estimate, + * x0 is the previous estimate, and + * f'(x0) is the derivative of f() evaluated at x0. + * For the square root function, the algorithm reduces to: + *
+   *     x0 = in/2                         [initial guess]
+   *     x1 = 1/2 * ( x0 + in / x0)        [each iteration]
+   * 
+ */ + + + /** + * @addtogroup SQRT + * @{ + */ + + /** + * @brief Floating-point square root function. + * @param[in] in input value. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + CMSIS_INLINE __STATIC_INLINE arm_status arm_sqrt_f32( + float32_t in, + float32_t * pOut) + { + if (in >= 0.0f) + { + +#if (__FPU_USED == 1) && defined ( __CC_ARM ) + *pOut = __sqrtf(in); +#elif (__FPU_USED == 1) && (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined(__GNUC__) + *pOut = __builtin_sqrtf(in); +#elif (__FPU_USED == 1) && defined ( __ICCARM__ ) && (__VER__ >= 6040000) + __ASM("VSQRT.F32 %0,%1" : "=t"(*pOut) : "t"(in)); +#else + *pOut = sqrtf(in); +#endif + + return (ARM_MATH_SUCCESS); + } + else + { + *pOut = 0.0f; + return (ARM_MATH_ARGUMENT_ERROR); + } + } + + + /** + * @brief Q31 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q31( + q31_t in, + q31_t * pOut); + + + /** + * @brief Q15 square root function. + * @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF. + * @param[out] pOut square root of input value. + * @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if + * in is negative value and returns zero output for negative values. + */ + arm_status arm_sqrt_q15( + q15_t in, + q15_t * pOut); + + /** + * @} end of SQRT group + */ + + + /** + * @brief floating-point Circular write function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_f32( + int32_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const int32_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + + /** + * @brief floating-point Circular Read function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularRead_f32( + int32_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + int32_t * dst, + int32_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == (int32_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q15 Circular write function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q15( + q15_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q15_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q15 Circular Read function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q15( + q15_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q15_t * dst, + q15_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == (q15_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update wOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Q7 Circular write function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularWrite_q7( + q7_t * circBuffer, + int32_t L, + uint16_t * writeOffset, + int32_t bufferInc, + const q7_t * src, + int32_t srcInc, + uint32_t blockSize) + { + uint32_t i = 0U; + int32_t wOffset; + + /* Copy the value of Index pointer that points + * to the current location where the input samples to be copied */ + wOffset = *writeOffset; + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the input sample to the circular buffer */ + circBuffer[wOffset] = *src; + + /* Update the input pointer */ + src += srcInc; + + /* Circularly update wOffset. Watch out for positive and negative value */ + wOffset += bufferInc; + if (wOffset >= L) + wOffset -= L; + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *writeOffset = (uint16_t)wOffset; + } + + + /** + * @brief Q7 Circular Read function. + */ + CMSIS_INLINE __STATIC_INLINE void arm_circularRead_q7( + q7_t * circBuffer, + int32_t L, + int32_t * readOffset, + int32_t bufferInc, + q7_t * dst, + q7_t * dst_base, + int32_t dst_length, + int32_t dstInc, + uint32_t blockSize) + { + uint32_t i = 0; + int32_t rOffset, dst_end; + + /* Copy the value of Index pointer that points + * to the current location from where the input samples to be read */ + rOffset = *readOffset; + + dst_end = (int32_t) (dst_base + dst_length); + + /* Loop over the blockSize */ + i = blockSize; + + while (i > 0U) + { + /* copy the sample from the circular buffer to the destination buffer */ + *dst = circBuffer[rOffset]; + + /* Update the input pointer */ + dst += dstInc; + + if (dst == (q7_t *) dst_end) + { + dst = dst_base; + } + + /* Circularly update rOffset. Watch out for positive and negative value */ + rOffset += bufferInc; + + if (rOffset >= L) + { + rOffset -= L; + } + + /* Decrement the loop counter */ + i--; + } + + /* Update the index pointer */ + *readOffset = rOffset; + } + + + /** + * @brief Sum of the squares of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q31( + q31_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q15( + q15_t * pSrc, + uint32_t blockSize, + q63_t * pResult); + + + /** + * @brief Sum of the squares of the elements of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_power_q7( + q7_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult); + + + /** + * @brief Mean value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Mean value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Mean value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_mean_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Variance of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Variance of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_var_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Root Mean Square of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_rms_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Standard deviation of the elements of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult); + + + /** + * @brief Standard deviation of the elements of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output value. + */ + void arm_std_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult); + + + /** + * @brief Floating-point complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_f32( + float32_t * pSrc, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q31( + q31_t * pSrc, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex magnitude + * @param[in] pSrc points to the complex input vector + * @param[out] pDst points to the real output vector + * @param[in] numSamples number of complex samples in the input vector + */ + void arm_cmplx_mag_q15( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q15 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q15( + q15_t * pSrcA, + q15_t * pSrcB, + uint32_t numSamples, + q31_t * realResult, + q31_t * imagResult); + + + /** + * @brief Q31 complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_q31( + q31_t * pSrcA, + q31_t * pSrcB, + uint32_t numSamples, + q63_t * realResult, + q63_t * imagResult); + + + /** + * @brief Floating-point complex dot product + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[in] numSamples number of complex samples in each vector + * @param[out] realResult real part of the result returned here + * @param[out] imagResult imaginary part of the result returned here + */ + void arm_cmplx_dot_prod_f32( + float32_t * pSrcA, + float32_t * pSrcB, + uint32_t numSamples, + float32_t * realResult, + float32_t * imagResult); + + + /** + * @brief Q15 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q15( + q15_t * pSrcCmplx, + q15_t * pSrcReal, + q15_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_q31( + q31_t * pSrcCmplx, + q31_t * pSrcReal, + q31_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-real multiplication + * @param[in] pSrcCmplx points to the complex input vector + * @param[in] pSrcReal points to the real input vector + * @param[out] pCmplxDst points to the complex output vector + * @param[in] numSamples number of samples in each vector + */ + void arm_cmplx_mult_real_f32( + float32_t * pSrcCmplx, + float32_t * pSrcReal, + float32_t * pCmplxDst, + uint32_t numSamples); + + + /** + * @brief Minimum value of a Q7 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] result is output pointer + * @param[in] index is the array index of the minimum value in the input buffer. + */ + void arm_min_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * result, + uint32_t * index); + + + /** + * @brief Minimum value of a Q15 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[in] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a Q31 vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Minimum value of a floating-point vector. + * @param[in] pSrc is input pointer + * @param[in] blockSize is the number of samples to process + * @param[out] pResult is output pointer + * @param[out] pIndex is the array index of the minimum value in the input buffer. + */ + void arm_min_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q7 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q7( + q7_t * pSrc, + uint32_t blockSize, + q7_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q15 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q15( + q15_t * pSrc, + uint32_t blockSize, + q15_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a Q31 vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_q31( + q31_t * pSrc, + uint32_t blockSize, + q31_t * pResult, + uint32_t * pIndex); + + +/** + * @brief Maximum value of a floating-point vector. + * @param[in] pSrc points to the input buffer + * @param[in] blockSize length of the input vector + * @param[out] pResult maximum value returned here + * @param[out] pIndex index of maximum value returned here + */ + void arm_max_f32( + float32_t * pSrc, + uint32_t blockSize, + float32_t * pResult, + uint32_t * pIndex); + + + /** + * @brief Q15 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q15( + q15_t * pSrcA, + q15_t * pSrcB, + q15_t * pDst, + uint32_t numSamples); + + + /** + * @brief Q31 complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_q31( + q31_t * pSrcA, + q31_t * pSrcB, + q31_t * pDst, + uint32_t numSamples); + + + /** + * @brief Floating-point complex-by-complex multiplication + * @param[in] pSrcA points to the first input vector + * @param[in] pSrcB points to the second input vector + * @param[out] pDst points to the output vector + * @param[in] numSamples number of complex samples in each vector + */ + void arm_cmplx_mult_cmplx_f32( + float32_t * pSrcA, + float32_t * pSrcB, + float32_t * pDst, + uint32_t numSamples); + + + /** + * @brief Converts the elements of the floating-point vector to Q31 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q31 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q31( + float32_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q15 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q15 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q15( + float32_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the floating-point vector to Q7 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q7 output vector + * @param[in] blockSize length of the input vector + */ + void arm_float_to_q7( + float32_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q15 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q15( + q31_t * pSrc, + q15_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q31 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q31_to_q7( + q31_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to floating-point vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_float( + q15_t * pSrc, + float32_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q31 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q31( + q15_t * pSrc, + q31_t * pDst, + uint32_t blockSize); + + + /** + * @brief Converts the elements of the Q15 vector to Q7 vector. + * @param[in] pSrc is input pointer + * @param[out] pDst is output pointer + * @param[in] blockSize is the number of samples to process + */ + void arm_q15_to_q7( + q15_t * pSrc, + q7_t * pDst, + uint32_t blockSize); + + + /** + * @ingroup groupInterpolation + */ + + /** + * @defgroup BilinearInterpolate Bilinear Interpolation + * + * Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid. + * The underlying function f(x, y) is sampled on a regular grid and the interpolation process + * determines values between the grid points. + * Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension. + * Bilinear interpolation is often used in image processing to rescale images. + * The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types. + * + * Algorithm + * \par + * The instance structure used by the bilinear interpolation functions describes a two dimensional data table. + * For floating-point, the instance structure is defined as: + *
+   *   typedef struct
+   *   {
+   *     uint16_t numRows;
+   *     uint16_t numCols;
+   *     float32_t *pData;
+   * } arm_bilinear_interp_instance_f32;
+   * 
+ * + * \par + * where numRows specifies the number of rows in the table; + * numCols specifies the number of columns in the table; + * and pData points to an array of size numRows*numCols values. + * The data table pTable is organized in row order and the supplied data values fall on integer indexes. + * That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers. + * + * \par + * Let (x, y) specify the desired interpolation point. Then define: + *
+   *     XF = floor(x)
+   *     YF = floor(y)
+   * 
+ * \par + * The interpolated output point is computed as: + *
+   *  f(x, y) = f(XF, YF) * (1-(x-XF)) * (1-(y-YF))
+   *           + f(XF+1, YF) * (x-XF)*(1-(y-YF))
+   *           + f(XF, YF+1) * (1-(x-XF))*(y-YF)
+   *           + f(XF+1, YF+1) * (x-XF)*(y-YF)
+   * 
+ * Note that the coordinates (x, y) contain integer and fractional components. + * The integer components specify which portion of the table to use while the + * fractional components control the interpolation processor. + * + * \par + * if (x,y) are outside of the table boundary, Bilinear interpolation returns zero output. + */ + + /** + * @addtogroup BilinearInterpolate + * @{ + */ + + + /** + * + * @brief Floating-point bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate. + * @param[in] Y interpolation coordinate. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE float32_t arm_bilinear_interp_f32( + const arm_bilinear_interp_instance_f32 * S, + float32_t X, + float32_t Y) + { + float32_t out; + float32_t f00, f01, f10, f11; + float32_t *pData = S->pData; + int32_t xIndex, yIndex, index; + float32_t xdiff, ydiff; + float32_t b1, b2, b3, b4; + + xIndex = (int32_t) X; + yIndex = (int32_t) Y; + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (xIndex < 0 || xIndex > (S->numRows - 1) || yIndex < 0 || yIndex > (S->numCols - 1)) + { + return (0); + } + + /* Calculation of index for two nearest points in X-direction */ + index = (xIndex - 1) + (yIndex - 1) * S->numCols; + + + /* Read two nearest points in X-direction */ + f00 = pData[index]; + f01 = pData[index + 1]; + + /* Calculation of index for two nearest points in Y-direction */ + index = (xIndex - 1) + (yIndex) * S->numCols; + + + /* Read two nearest points in Y-direction */ + f10 = pData[index]; + f11 = pData[index + 1]; + + /* Calculation of intermediate values */ + b1 = f00; + b2 = f01 - f00; + b3 = f10 - f00; + b4 = f00 - f01 - f10 + f11; + + /* Calculation of fractional part in X */ + xdiff = X - xIndex; + + /* Calculation of fractional part in Y */ + ydiff = Y - yIndex; + + /* Calculation of bi-linear interpolated output */ + out = b1 + b2 * xdiff + b3 * ydiff + b4 * xdiff * ydiff; + + /* return to application */ + return (out); + } + + + /** + * + * @brief Q31 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE q31_t arm_bilinear_interp_q31( + arm_bilinear_interp_instance_q31 * S, + q31_t X, + q31_t Y) + { + q31_t out; /* Temporary output */ + q31_t acc = 0; /* output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q31_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q31_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* shift left xfract by 11 to keep 1.31 format */ + xfract = (X & 0x000FFFFF) << 11U; + + /* Read two nearest output values from the index */ + x1 = pYData[(rI) + (int32_t)nCols * (cI) ]; + x2 = pYData[(rI) + (int32_t)nCols * (cI) + 1]; + + /* 20 bits for the fractional part */ + /* shift left yfract by 11 to keep 1.31 format */ + yfract = (Y & 0x000FFFFF) << 11U; + + /* Read two nearest output values from the index */ + y1 = pYData[(rI) + (int32_t)nCols * (cI + 1) ]; + y2 = pYData[(rI) + (int32_t)nCols * (cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 3.29(q29) format */ + out = ((q31_t) (((q63_t) x1 * (0x7FFFFFFF - xfract)) >> 32)); + acc = ((q31_t) (((q63_t) out * (0x7FFFFFFF - yfract)) >> 32)); + + /* x2 * (xfract) * (1-yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) x2 * (0x7FFFFFFF - yfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (xfract) >> 32)); + + /* y1 * (1 - xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y1 * (0x7FFFFFFF - xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* y2 * (xfract) * (yfract) in 3.29(q29) and adding to acc */ + out = ((q31_t) ((q63_t) y2 * (xfract) >> 32)); + acc += ((q31_t) ((q63_t) out * (yfract) >> 32)); + + /* Convert acc to 1.31(q31) format */ + return ((q31_t)(acc << 2)); + } + + + /** + * @brief Q15 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE q15_t arm_bilinear_interp_q15( + arm_bilinear_interp_instance_q15 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q15_t x1, x2, y1, y2; /* Nearest output values */ + q31_t xfract, yfract; /* X, Y fractional parts */ + int32_t rI, cI; /* Row and column indices */ + q15_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & 0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & 0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 13.51 format */ + + /* x1 is in 1.15(q15), xfract in 12.20 format and out is in 13.35 format */ + /* convert 13.35 to 13.31 by right shifting and out is in 1.31 */ + out = (q31_t) (((q63_t) x1 * (0xFFFFF - xfract)) >> 4U); + acc = ((q63_t) out * (0xFFFFF - yfract)); + + /* x2 * (xfract) * (1-yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) x2 * (0xFFFFF - yfract)) >> 4U); + acc += ((q63_t) out * (xfract)); + + /* y1 * (1 - xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y1 * (0xFFFFF - xfract)) >> 4U); + acc += ((q63_t) out * (yfract)); + + /* y2 * (xfract) * (yfract) in 1.51 and adding to acc */ + out = (q31_t) (((q63_t) y2 * (xfract)) >> 4U); + acc += ((q63_t) out * (yfract)); + + /* acc is in 13.51 format and down shift acc by 36 times */ + /* Convert out to 1.15 format */ + return ((q15_t)(acc >> 36)); + } + + + /** + * @brief Q7 bilinear interpolation. + * @param[in,out] S points to an instance of the interpolation structure. + * @param[in] X interpolation coordinate in 12.20 format. + * @param[in] Y interpolation coordinate in 12.20 format. + * @return out interpolated value. + */ + CMSIS_INLINE __STATIC_INLINE q7_t arm_bilinear_interp_q7( + arm_bilinear_interp_instance_q7 * S, + q31_t X, + q31_t Y) + { + q63_t acc = 0; /* output */ + q31_t out; /* Temporary output */ + q31_t xfract, yfract; /* X, Y fractional parts */ + q7_t x1, x2, y1, y2; /* Nearest output values */ + int32_t rI, cI; /* Row and column indices */ + q7_t *pYData = S->pData; /* pointer to output table values */ + uint32_t nCols = S->numCols; /* num of rows */ + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + rI = ((X & (q31_t)0xFFF00000) >> 20); + + /* Input is in 12.20 format */ + /* 12 bits for the table index */ + /* Index value calculation */ + cI = ((Y & (q31_t)0xFFF00000) >> 20); + + /* Care taken for table outside boundary */ + /* Returns zero output when values are outside table boundary */ + if (rI < 0 || rI > (S->numRows - 1) || cI < 0 || cI > (S->numCols - 1)) + { + return (0); + } + + /* 20 bits for the fractional part */ + /* xfract should be in 12.20 format */ + xfract = (X & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + x1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) ]; + x2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI) + 1]; + + /* 20 bits for the fractional part */ + /* yfract should be in 12.20 format */ + yfract = (Y & (q31_t)0x000FFFFF); + + /* Read two nearest output values from the index */ + y1 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) ]; + y2 = pYData[((uint32_t)rI) + nCols * ((uint32_t)cI + 1) + 1]; + + /* Calculation of x1 * (1-xfract ) * (1-yfract) and acc is in 16.47 format */ + out = ((x1 * (0xFFFFF - xfract))); + acc = (((q63_t) out * (0xFFFFF - yfract))); + + /* x2 * (xfract) * (1-yfract) in 2.22 and adding to acc */ + out = ((x2 * (0xFFFFF - yfract))); + acc += (((q63_t) out * (xfract))); + + /* y1 * (1 - xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y1 * (0xFFFFF - xfract))); + acc += (((q63_t) out * (yfract))); + + /* y2 * (xfract) * (yfract) in 2.22 and adding to acc */ + out = ((y2 * (yfract))); + acc += (((q63_t) out * (xfract))); + + /* acc in 16.47 format and down shift by 40 to convert to 1.7 format */ + return ((q7_t)(acc >> 40)); + } + + /** + * @} end of BilinearInterpolate group + */ + + +/* SMMLAR */ +#define multAcc_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMLSR */ +#define multSub_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((((q63_t) a) << 32) - ((q63_t) x * y) + 0x80000000LL ) >> 32) + +/* SMMULR */ +#define mult_32x32_keep32_R(a, x, y) \ + a = (q31_t) (((q63_t) x * y + 0x80000000LL ) >> 32) + +/* SMMLA */ +#define multAcc_32x32_keep32(a, x, y) \ + a += (q31_t) (((q63_t) x * y) >> 32) + +/* SMMLS */ +#define multSub_32x32_keep32(a, x, y) \ + a -= (q31_t) (((q63_t) x * y) >> 32) + +/* SMMUL */ +#define mult_32x32_keep32(a, x, y) \ + a = (q31_t) (((q63_t) x * y ) >> 32) + + +#if defined ( __CC_ARM ) + /* Enter low optimization region - place directly above function definition */ + #if defined( ARM_MATH_CM4 ) || defined( ARM_MATH_CM7) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("push") \ + _Pragma ("O1") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) + #define LOW_OPTIMIZATION_EXIT \ + _Pragma ("pop") + #else + #define LOW_OPTIMIZATION_EXIT + #endif + + /* Enter low optimization region - place directly above function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined (__ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __GNUC__ ) + #define LOW_OPTIMIZATION_ENTER \ + __attribute__(( optimize("-O1") )) + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __ICCARM__ ) + /* Enter low optimization region - place directly above function definition */ + #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) + #define LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define LOW_OPTIMIZATION_EXIT + + /* Enter low optimization region - place directly above function definition */ + #if defined ( ARM_MATH_CM4 ) || defined ( ARM_MATH_CM7 ) + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER \ + _Pragma ("optimize=low") + #else + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #endif + + /* Exit low optimization region - place directly after end of function definition */ + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __TI_ARM__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __CSMC__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#elif defined ( __TASKING__ ) + #define LOW_OPTIMIZATION_ENTER + #define LOW_OPTIMIZATION_EXIT + #define IAR_ONLY_LOW_OPTIMIZATION_ENTER + #define IAR_ONLY_LOW_OPTIMIZATION_EXIT + +#endif + + +#ifdef __cplusplus +} +#endif + +/* Compiler specific diagnostic adjustment */ +#if defined ( __CC_ARM ) + +#elif defined ( __ARMCC_VERSION ) && ( __ARMCC_VERSION >= 6010050 ) + +#elif defined ( __GNUC__ ) +#pragma GCC diagnostic pop + +#elif defined ( __ICCARM__ ) + +#elif defined ( __TI_ARM__ ) + +#elif defined ( __CSMC__ ) + +#elif defined ( __TASKING__ ) + +#else + #error Unknown compiler +#endif + +#endif /* _ARM_MATH_H */ + +/** + * + * End of file. + */ diff --git a/Middlewares/ST/ARM/DSP/Lib/arm_cortexM4l_math.lib b/Middlewares/ST/ARM/DSP/Lib/arm_cortexM4l_math.lib new file mode 100644 index 0000000000000000000000000000000000000000..49930a09c372cdcf8f6bebc732182c46f53fdb60 GIT binary patch literal 2259776 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�TyJFW;G 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 (mz7>o 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�P>$)~ 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 OQbvZ5-W5*u49o>|%?ouO8OrDvO34dl^a`bn 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 z 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

DQcI82)HQ<- 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�bdFR`ao*Rt2x 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

8{87qicqSnT|MjG&(2#jj6+))6w>0ADL>b{VzH$ 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

hOTE0`T}i6)+4GC#K#~kHa=9$i=Uy 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 literal 0 HcmV?d00001 diff --git a/Public/img/icon/1-HART离线.png b/Public/img/icon/1-HART离线.png new file mode 100644 index 0000000000000000000000000000000000000000..2f3ddc84185017a606ec6a11578d921ef22eee9d GIT binary patch literal 1532 zcmb7^`9ISS9LHBVH*>_O(U47yRtY)N#$024%=Sn^hRED^CBCkab5UQJD+^hD6-!D* zqU8Eg7#1B;bBi2lu6^|-~JZ9=#D=QIFRu>{J&Q&YTdchk&Pq~ok6l{ zM^6Esp?@)M*EGNTvLNb|61bB|hT5Ku0D+X`{%BX1=CTC{Bx-19g(Y9KoG+RlDpr$9 zwRq}eBex)=LExwsk=CsGD)TtuK^DZiW6LXu5illShZ|ZtBCTom!+-((h`yO9Q$4%;j0h#@l0s+WSbVPU zrC9gFZeQDuH_eHEl=~c&q*HwVgxTw^$i)KJJ&n`In4IWD8)WvPT1~*W<}vd_9KXhk zs^gE5&ne!}&3UqTjj`P-calZ)n!Tct!GSh@M;6?WMtjAqW!9dJc#eC(yzBqc&>-M@ z8lM!{TkOR?P*gq~wFfl{4^|VsUBz3Zy`XC$$9a-cjw10c1prYylKr`{IarE+%)t*HR_3;`dpC z3ElcvlcU=QC5!pkdh|(n&?>Mw^qD%Q`a-d8`Kf7R?@x_|WGrW+9I33mie(?B%aq~_ z8yS&Cx4`y_-h{cx{KpWcuD%XDG`WDK)E!qTV&7lC)r8o_-^{#68xo9RvOs>V&EL2N zHbNZoEj9AOByafUOho-YnmRA(u!jF9in>Xa(OyXfJM7wnJ5E#KzwJ$>7P`rG70H@- z)^K9=kLRzNGe_Q!OLTT?wht=@k__kw_vtlsk|K9ZDWH`n-n5eV^O35uH7qaR5%r!C zcRwSmOln>I*SRSh-U3V2^BatNx{S{|S60a@DobC5S@&JvlG5)YZd=x@&zAMQ5FXXH z-$EpfYYUQrtT~;vurH z(u(?Yrwp~4LAy3^PKEKR`iSJ{mfa#f#=$9f71d~@<`|qaMAnDh04sD!Q0op@2gSIf z44|K3HM;{xz^St@C1}f+^$4r-AHbiCZ|NwE;LOrKStxfp|IDGbAopKICC_{OOUqo- zBDV;lO`-~!;d&&EmsNMFEt|s=RLJS(l#rW?FXMAXu-zPwQFblCy+x#uXPYMz!E(aB z*o0&8=lvh-lkXRMqH9i;##;@xIZBe>9K25xmPw(hkZxBntd=dKlTYtvnJEUb_)4Ga z0qQZhc7cztC0-`m`JitI6uQ>gqk)PP_u*(|6V8NzT?ZY984Dj=uC1#m8U*S^=b`Y@ z;&FOu`113u9Rq`z@#|rSlG~V%_L(sa`8m`IPD2LjNN;pSs702Wzpjb0hG!kH?Qo#Y zbtVob(2VKDK=At|bFO4H1(x<3Ur%p+l1}oMMwi@!xcIi`8@@6*7;M^~v;;VydSX1E z1$nu)6PKqnpJA5Lrq*l$v&-e!W^X~0e|&67F37P0iO>nURwv){4^qpUScTTW(wV-x za$U@Ud+1z@mVHq{Y}iD_UWD*0>d@7%d_CI4@2eBM_^G+2XWH16>&Nb59%Qt;2|L;b7rF2t{ypTKbt}G4t&<{@q6S bx#KePQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`jRSl_T!A#HU@@!PNuVBqk|4ie1_1>Fhk%5F`u_Rr_n*K2o;9!~2Pnr` z;1OBOz#uLN!i=ZXKHD=eF#qv%aSX|D-h2Dyt~m-kYzZ@KMc@C=(w?wb+@3gp|v7f8#ld!9bdCgW2{+X?OmbWC!SuxufetR&_-LeJl9xvc8gu?(^m(DT7G9zePy!Za!LCn zT{*5TnL(1<-y4~)T6+8HowThb*3ZJ3wicvY==6K&-Vv6W=CGj_c7b{ z@`P&{SD&)7>Q*|;)y)dMbVGRUon72PD;8OMORo-Bjcrx#HsAYe>Kpb+$0OFCTXa); z-?9JRN1Ijm`5hNu8$EYH6xS`MlJ|>6v-elERT=dN%RBPKtY~7v=R!-Em5|`!&-oZ~m+GN4K<< zJBLr&c~>jbmFIce@jC0v4z@8p52gmzEInu%ICE)ul9C>Fh6sCj#Z z8|%t9%2#Klm6mSo+N~cF((4ebF83jw>(+}&Z`XH*$lOWq`gXl4#Kt#gtyt3XMX8ax zM+Me}x?bOL<3-TwN$W0N+*K8NDPq_6#o?~ItCnnv6Rn-;Ds_9|w!8;N7Wgf5|LYMa zw?+EW;;wDiJ?>wtDz6H)iP&~+@7GlorE|hoT>Y}Tq9?EVJ~-_gh-6xZjG$dFzcrt1{ovPp$7Z zX0M(Wta;Bg?DS5N*Rxii=?i{&Yjw#!-E2u4yQLjNY=W&Dm?rc0J3Q+`YZ6C#bZ2MQHhiUCV0f zzw_)^AARcIPyP3eTGyG6S3IpR&-MQ)dg9Ud`&>LcKmQ*7Bk@gVV$8es{yT2{``x$y eh{0Ktzsv?#_%7|vYg-8_Y&>24T-G@yGywpA2s1MP literal 0 HcmV?d00001 diff --git a/Public/img/icon/3-解锁.png b/Public/img/icon/3-解锁.png new file mode 100644 index 0000000000000000000000000000000000000000..6598b52aab588615f7fa8479568094dcf617e89a GIT binary patch literal 2656 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 literal 0 HcmV?d00001 diff --git a/Public/img/icon/5-禁止写.png b/Public/img/icon/5-禁止写.png new file mode 100644 index 0000000000000000000000000000000000000000..723a51732409343d3ca97c6f8c4af6c6f80b5e10 GIT binary patch literal 3901 zcmcJS={Fl%+s2a!4JAT3sL&uSHP@K7v@w&G;#35s#zWCcIY>B2V+f^Y4r*w{P!cmu zYYtjN&59C~nu?a_fKoi3=P!7_ydU1*DT6eNQ$+9ahX(a;}RD^nvJ zM>q8~a#avCs|v!c=M~)7Vgtxa8|Adutn*VyQq{J>&WyIUV=4*B#)3YYYW;WN1OgdO zNOAuo1q4cePX>cyebIu|W@yQ-3)(-Y4M8CHGe$nyTHFxW)0y`^XSgBB=0X)7(?|r` z*Z@W@thD;g)fC(*n!$$)x@4kB-w;V$X+UA%*OOy7()#{}^ zP*>GN+s8*e+1-*-Lq=7(wz$z=H+zv?&<=n3OleDy^z1hW??JYn4eAsd2%WH(Rmv3>% zG~>Gh$vh{lKoCUfckGpeC<@SmpV660eQxJXeW-~(QdgZMxo98?oj->?0A&UR`GQq( z#~-mD-0yHE3rLMCQVw${dcrE=nQI1>!hl|A*9b#fSmWTT0Ysv#H#oD~K=N8U9b4gytCWJ?4E_ zhCD|{42Q7%l6WIZ(77$!PB68cR2^NF{FuW?oYM)+uexIcO?^yK9l|OdzZGZcUws=- zrp`9Lce<^K&gu|>OH72j^BZQklH;84qCf%4hWH{x3(ViP&k{ovbH_?boa^dd%i9K z5~0N;jt^NG29;1c4OL9tp8mW1s1E2t;9r)|$yZzOs@u7SxMVTyGde{gB-NC5Khtqg z)E1~`TN)IdoO2(}~jgyIue zS24n<=_}2lE(=b`)3B{E>4y5%hK|C+7XGq254*>*bLH4qBE5hvnrJlEvxImQS_K{4 zbbb_>Q60J&_Odel_^5qRH$AJMoL#TyffD5oeIe4zMzrOXv%@%u{1o=4c!1U2smIwh z`E&UcxfOvw$R-@0!a|IOhCIU?LPI?wUS9bF&Z{E0gLtBa9!it)9r4V$JHK1UTu?fQ ziMC525i*1>GdM*FP2j4TA@|N5c=rKOi{GGwZYq<$i&ED-+VYIy7-hqac;Zmfz-?bp zv<~0i4$ix4YJsGxE1oU2T2~0zmb+0ryD>vtnhjv|RIhIz<*UYD8_Ay z(b9ws*z?Tg!idNSAw)h~-rM4jN48saXW?_HDlIv}9tjfzdeOFrrjk!hhivNqpD#=KqIEEEiQW9`ZQTv*o(9heVUMjT zjiUc;ysujwbrV&upAtw^BSKhm6(qT1!jttuJmDM6zHpGMD+hP+n84*8jM6!fsyEEz zi`CSt66HwZZ3A~xe&`-Z39(9e{Taw4>w7ko6s&n8!z5An�@+w zMc(4fZMxXTnp0mS>0TB#_yzc|Qx4p{(VZy_!<7BY9os-Qy78jCF*=dRow%!C`$xE3 zhT;Xp#N_$lDrX?H2f7{9WyGy1ePQBq$#^B$w3MWveFnZdT@$mp45(?;$IuDNtNu!0 zlL8E#WT_wgSF8u8`wr~ct$_ju?!@piyBjSh=dj{I9ESKGosTj>OZ-x#9SLRTL&tYm zv>fYHKkQvde^l)v(Q$K47fdlm! z&yUA7>C-(8VDM`w9a8#t#Dx4r`Q_MocBd3t`ZySo7=Duqfu?Egrb z>vCg}xQ+328Q?XEJDW-<<@o;h%z%>;fdgQ$VD+elU4j|s6Z(;hf&ROEvoZG>bf`jE~ zT9sPedY?Ow;Q9W^a^iPn<};HhoamVM?fS0uLg_h8MkRH1=No+0y0)*t+eARJ3lm0C#TgRSA)VM`On}{z)DKMJQsRL|4ucwTKhXo% z3w2^;`NhQkvdb8CJI6x{Df%(;_Keerb}m&X*7Lf%Vb*!nJ|C*FShl&4WpVOIb&#xh zNTOF-n^tS!Qv_1_F{mqz^2~2y!HD^AfIxK!?NA6g640N~BTL$5r_fI)dIhvyYwiB) z^MZ{A!bwGtsC5H>M|PA zyg~(;?>3CU6r*)wSTq0dFy)`m^QXi@Qv-S3!Z46T9RtQpS^aL0>FCqpW~VMeZ*FLO z?+JBX?lhrX7YlW|ZZuO=(+7t9iw_yAP+kO6w=;#M=`=8U~ z(1+P1=i0eD;PbjV%o{B6=S?eBSQH4>-zgsH$_qIi zF<&dAY(slx?eSS>JT#$4FHw3ocjQy~CQ*aQ%utotV&}h5t?)`e#dH_bS6A9EN}Hd@ zWTXVc4ZJtMSQv|QLloY-^4!F$7Ox$|q%PhZHK3)K?NfQmqwL9%{FK#X@2BP=uHizR zUi{?O^TqN={KQx*ZvziBM(BFdLItj2Bxbz?grFK!Jm;BbdBh3W;dxJ2$VcPuE6eCB zF`27zoZZRg<5W~R0oEVi@aO~0pE;sX)*94*9OvUTXQg!N@}R83IRSW>@kiF75_?c40QEdPh4^TamAuSF(sZ&C%F*QD5)+T$@}I z%Ua9l^I`aM@TZ)Pw4r&u9MZyEil}k!l=XvezHgJYF`EJ^MdrZno07=swEAtUHL}T+ zZk(s>ixM7MVp?8rq`MyZ;0q51DVppv|G(h9c&=a`AnBP#!jRqfbUMd# z^Pu8EtYct`0)VV(f_*jD`}YMLfV0`i(8zmTZBtB@1|SC-!ylp2K3)QIsJ6jdt7r^A z!>fSpS&3NQq5ZzGPtKozOkzk0kk_r>lK z8pp%_7OX-<#ON%PRL|-8ueL1(T*ccSpcwWQ3=zt1@M*3cQ53gmv7UZF(hxJuzwIat zC5>pA**Y$cH3o4m38Z&F9?{|&t{IjXq_zlmZj#`7_pT0PU`i!+#3$T+RC8`~_IMt6 zpW0);R*(ZNI-db89df){zIZk2uEUCmZmTWnhw0j)W89a{@G$i{21w|`z}?o{J|b3! zRfpSjr9zeFzHQjNuL~~Hb!Bm1AjBqB5;?x!4uO<@5_Y}Jxi{Pb9Q&5p|GPLE^R?#? z<9FS^;cpiWpuZk2v7|yiMrLixV$F50JGmn7OW4m}8%us#SGuw%ZAeSK_Q5%pC)rQG z_+B4T5QZSuPUKxkCjqi8@8$UCgTbcx^uSW?^9b~X+c_n-T(jq literal 0 HcmV?d00001 diff --git a/Public/img/icon/6-蓝牙.png b/Public/img/icon/6-蓝牙.png new file mode 100644 index 0000000000000000000000000000000000000000..050c83141b73edc8105978d87f24d31e90a953b8 GIT binary patch literal 1886 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 bImVmY@C!&8gOqg!ybmFMTQ(NVe>wg`tM{ z5ZOzbgc7np_k6#<>-XRD$1~S87w`MbectCj_v=3Ab-42 zR2ZG~D{AB0apZ``+(EePpcsY&M?%0cX_|Ie@Gm1NjYIFZE0jwQDJZS4$21s+Mly+n z6ClhYaCW?i2dKr1ut@#5XyAx%xMv%q}wgwApNHnqcwlt-g&8~Dz5JIP=Px1&6CkhIc74u#v}5-+*?DNmq^9%v>vC^qTt*P-fi4jVodUkNFF zCX&2TonyO|42Iwn6|9pGgTBCZe`l>4uRA4h`F?X92eSrH61Xx9eaW;c)_&*CohD=W z8UdoOV{e~l&+sR<)}|hp1#`oqFVOL-`q$xUx)y%6&dW*}_CrYIyZ6?niqF#=wcPqp zkabSf?Gf5bja~bYpnmvgrlPWvl$1{BM>OaE{z|GPn)mp9tT08tM%uYS?T2d{x@*|9 zCT81%D(m=}MWyv0f1jw$R{wKNRZZ=NO$vq+UtFHA5o#t7wog1>yQQ5mA?k)fdr7|V z9I;|7IKMvq(g%GCHRTGmHwHuFZk3N7?9PUg&fo}rh~_k>SNE#p%tSLVXPv`Ypc?n; z)W0Yp6cGpyF;oti@@~S`rJhYKc^EI_Fl3CA2UDJat*WLsD-HTkaJi`jE=_>QEEhaj zw~T*!<=aN|$%7k~T<7hu_+nO-jOlu?TSISpGXulu>}L}8CEaM;t)fvaU{3Rfo4bazzDd=!YMlD8 zlFCf8x2V)r-*~ha?F!@3w6OK9!?hP5JjxSCfHl2`MJ{~qlqYA!ucl>*s}K>*G=2}O zgKX;UuiNBJK}a0@Tl7(28xaWuomtBvkM z$bhUJ)|Fo~%tF9|yC-qygj3qG1OpdV0WV(u^;XE1k-M+OZ^k%@WxVFP$x#TCtaGQG z6^DZ>G}f}-UOD6vXTElHcUhax-MdZuKR7ypU&Kx|p2CZ8@TvM=V?6u%=Gzn$j)nhH zpw3Z6CRXqnj7?V ze&~Fpt$+@bq@$uAUTV z;@uu97)>=7>)$!r-^Rfa=VcwMq6E0(*@a|LOfYHU!@GZ0EkhP8I#=?1;HWS8m+t5t z*-PZL?lJJ--E_h!)s^Eh`lE+LbIaAw?JxGXEu`BrRQux47c6d%R~57IB}v&n&xDVr zTmTx7@lZ&?0)-p4O|2X)`|SJ^m;->U*X@vr=|s(H;y_aRJ_PKI1acSmX^rB zKY1GR+HMZUv$+^ARO7-on5wmp9OK~re?lzFYrAKr`JxBFrBDz@gs^UfSf@_RSgT?ys#=N0A(Y21ndZ$o& zu^`^xsxU8n&c=Zoof}oR_YJG<^c>+u=>vq2Zw<#`niq9{ebYW^hu=wkrV&~bt%6(G zlZ8(aAdwz3Eq;^*VYPc}cBo}pzv*VnlL$D9uz2n_=hmM~eqL#xo6wKT?qow1J*%R% za8M`|hXueYPR*3QVI{!J-E|0=1?G%TKJ<8eUIxy}43pL`d^a>?#dvy9(z*i48=%wE zmHX?(2dxYxxEFX~$%EZ>3PHI2)(1h1p!5#`7&w!8m964w2cwU-3UT5W4u7RaUvs&L^S_LIY`{(;)BComdB>e* zg_{Nv7R^+sX+>!u05~BnKfjKR4!82}fiA<5oBf;N;j2I)2E9sa>l|LL&VW1yNJ&@f zb6@O#MEPOZ6nU_N!~SI^kbG2)`|O#FcWff-e56bC(KgU|ibOUXrhnL+ zoLbf{s!BIebKTlS8%GVzN(1b6SXp<$oHD=ra2^?ZxOZ$a>xsKiX3#ufGOJv#LN{zw zHF4;nOkn6Ymy`YMJX+Kil72}D*g;slLPyWYmZ@|BE-qf9mgd+Q)>tOuOhg1T2hD5y zy%43IDAO_5%|9Q_Yt_;Yzsf~RdM8X0AWjS0lPbNW^TfEYxwfP>GkyuYNvlKYY zxgQZ6GuQQ?_9_2hyx@K0n5!ExZUr1iY43z=FjHq{!OMTT88zmr5Pck>%#Ks``8QK( zz{C#ArWm^J7!oHMzMQOT%&Yl6U#-+r@8joAd>9Lf?3SnOQ{nFq7m7Z-gNj3)93M?M zBH0AguZ?juxI)$6RTf6o`1>mDuFpy($~P|dIRK0TwNgMW!vFK7kei~PDopuMai)*X zoEwiocK=;^jKhY}lE}JCOH1RX$zO(Z6~$OpR>EcMwcr||>%dwb0z|-_h-IZJ=8gR}#XYs}K z&Ay+kW(SZUx2W9xXsTKrp3bio(N-qn-;a30>EO@y@Lqf#vT@OXV=PiE-3|KY-Obd? z75=X9<>h6u$Fd&fHSN(|b0EAbJ^$r)_EpzI3++V}T z=TRkr>FMdk&l&Ru!rN*r5n-FIAwe+c$~T{gy|3AnyrNt@UOX|ungA&^n91?l`8i`d zhRG1Te81{PtOv+_aMn9#@NV4FfQ`-Ocy%A||G-J)OS^PCI`Jrt2xKG#fr&+cp;Iah z#txU+8<#Z>2nNa@ygZUHLL}VQSB3cH51;x{#3261^>g4hw;n`0FX93SRyvF=25zRoiBgdF0cJTP83r7HJ|ASw%Q+ zWi|fb}HHNMPiwAIoREhOGK6tAU%D+ zkRpF+rL$+xQe6S|U=CRlC$+;myrtW0`e-FzEeH%u~E@o+BK#`w> z0cy?bN0R5k&QCGcL#! zw6Vd%VU4bW%?-(l%!=w2@>YT};0QZxcv(e7 z4Ii^<(6@6-{4JmBh!MuIj{JBx!HHU1TUE}ymGp`MHQ&9ei6Y%NVCWNa_98ec6Ra3d zN5_1i${mFEz2%H|Op(x(3krI(I$kMI#VcH#7aPCoZmpPIEeq6h!A`%?4F<#(mvD(n z$Hup>eEgi4$Zb|d3j8{hMR}w9@o+e!EgraBwLm-CnTs>oBHJxn)@j@{t|B~1=uYaB zCyy(j{8oMd9c(>l9GJ*Q|TP#*r1_%4(g4bAHjc$pk4 z@r%vxXcSZmWo07sVwoS6KxZPPv?%;XeXB8S=~N5Yz=)*Sh(Zgz8W#;$<81n2xk z7xdZk6`R-GU6KqgAtHmEwMcCa_;V;dJ|_j@OtvGahA7)Q84-o#dgICGP7@#AB}-a z*y1UaL2U2-_K%4l7|*Wz+i=Ua#%>7cwAB047>wu_CQ(*LORHIKPcn}JBJyqk!}Ehg z@Sp9VyspfQs&CJ*o@(rXfTUjQ9A^Bz6@-eqtEORKC?g|dg2i0&s2g;M(gv9?+GH2E z*EZZ6l`NlcHA)pks4WgmBbvXu>`QEq$=~$bFSz`mhUcl(KJk67qLH{ngq;I+`cXyZ zdH>}%$>`Yr_$>4#(977?vo@An2hrOD*Z(LB?WJYe;N)Ta{WZW)-BqhL!gI*(&zVYR zS7UDvyqt@3g`}gMEp|ngJbkJn^UAu$MyKf6bAokJL@MFq$+qHc2P?)Uo?*AiS_H?o z+S$(7`wy12mg{NHNb_T3$>ce}D0AxqU9UrL^JH4tD?L^A5zjcsRwt>y)tYlpSF+r2 z7osEY5DMORMdSjoX^Y3dN>Q|dW%*ye)nww{&oO_0Bn5a^wohR_r~RkNzy@? ztAntM3NJU&RZf?Tt6#ME&)SQ>cP=7r?tLq?mE$iT4+r!?CgavcGJ2{Eb#}YN()d~E z(m*02{2rYH7Szc$au>?S1sb|`>~pm=Vq}QSXT_^{o>)-|K-rYR+{`|OkOsSVzfq!m zT`h1yCs*g-p)`?N;CESMTJ63(_s(PG?5}CVlFW_`6S*#Uh8Is7utnIoTD8Sz(oB3* zc43Gd!R7o)C(~-9nX~QM%KEG6*TtFlzl~R0qhUX3Yak#6);M188kr-Yp0{q*^3XVOnOzmReL(vOgJD3$n=Vw| z9VT9EWpa+FZ!KD9ly{77b?h`1N zOw=9eoUqi&x?}TQ-qSH$pdyvw1_=8^oli0=A_am%oYF7qL!2*ytK8d|t6ygg1|dg^ zS%EnidYdI>9dr!g0?dkuiHVeBotB_)?{RDyz4*n)a@|$3mzr7*YxxqNQ44>Hpe|2t zZ})y#89byh{pC^n3;12|8NVF64ysfs=3h)6&;reHD<`ku-HmxUX6C^W&yO)LJ^bBp`TV0wVKo-z4WfWpbbn@pdo0DT5npijkb8qOSN zDm-N2pc8!SeZJ&(Cct!3zX2?mjGf|}C&^1mnK-TOXfIL65(&?5N30dz&-5ZP{gaeH`7OW>+3;C`U^z6_S+GhUTm#sWl(iXSvf zW%-+^6roJC%nP_;1B4!&e9m8cEGY79cvx?28EEUd_x-yZPA$tZeFLos(5I^Ga9xGX zbtEvb1M{3hCa&XTbN9HJKMC85Ok6)c1E6q*%7Z$>y z&Y`m*lqF%Gxt+61r-4sEdkF`Juod8o>xIM(FNLB4so(=Gb(!z6ah2%5z4Yu=EOD|T z{_a2v$er^z`3qs{gVV7^Gp|AeP(}$FQ~N2m7kXo;<2G2(LAB&zaLRbh(F*hwC?Laj zZmWk-%4APBf!hdN3P&gvrQixdtoQ`{d|IzaE%)OR?sndu0r zg~JCT{kyhpLWD~AxHZGYsAPA^w)ca!v<=9}--0|Qe09rBDa3@LXd0H^$ z@8fz#=+FZb;H;fg9QjUyVk2{aZb;KjRbR#^7Sf6{;~`fynY$WEv( zyjU0kWA1vLg#eXV8!y+V9}PXu0Ok;Y57mgjfv8oPl%|4sR)6=vYzAz%ZN> z{19~7=)@o>RU1H8H)26q=TJA(b0iN(=Hr(l zD%^Zi6+>1QauJ5FQs*r6#o@@2KtPgxb(J-4Ej8+oDD~A~Sp|FIBq@GLBDFWp8oN#< z+ae-;Z@@-7N9iviq4&VG8yI&8=n?}3idIY1o5_e5Ur(iEf_tl3&Ktoq0R-0%f-T5@$5T}9`B7Fc&+aHV;nEYMU6uH`7*S9U>=#*qcw|Iv4d z)=CGxDj*^PWBpI~d)}eFezYz>QxCxbRaC$LE`-txmADJtS^H!i*|#cd-;CtqilqYY zKT+;k083p@l_=9;a1BI z-6-|W5F9bVVJDa7qm=b*mncc*XQC8@(n)81*QMZAzZr36=0--~pY~s?b5%p+!xt?( z{bc2Dwaks24%+OFExtEUtNfN(ZVk>|<2=}PYxB!sUmDrL48KoJhFt3U*T9m5`IJ=i zg$HZ^G$&gFTu`eJ&TKbN&x-w6vLCoE0v4D7(XC)yLQh_Meb$aUIdZ-I8(7Z{)otY_ z*~a}-iB*tPA?@eg9DHy%go-ZE+Q7-*gWaYNitfQ+FnaZtrB}LF`aXa&Gt_$T=ky-6 zT-ZBt_o)LH8^_7K$t!RZaHFy12Xf|dXyKbH$-G~q31fi5WgPZQJOLD-eI!qr)CxKS zdn|6CZ;SQ^m!-e`K;rbbva;$1VPX(Cq@^7|oHW@fvraD7?*>S;F8nfFOKPfbP9&vRzDeRQ}p_as(UzRPvL zFZj{uAME$ESS^KF_xlw^LGKH-{i9~mo>RR910 literal 0 HcmV?d00001 diff --git a/Public/img/icon/f-禁用模式.png b/Public/img/icon/f-禁用模式.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed1f3b64c224640e29f18516321177573af4d92 GIT binary patch literal 414 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 O0g$Zit*R`%FZ~yw08w=S literal 0 HcmV?d00001 diff --git a/Public/img/icon/loading-1.png b/Public/img/icon/loading-1.png new file mode 100644 index 0000000000000000000000000000000000000000..429365a6331922726f713a9d0cac09d1ec6fc9e3 GIT binary patch literal 2646 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 literal 0 HcmV?d00001 diff --git a/Public/img/icon/m-手动模式.png b/Public/img/icon/m-手动模式.png new file mode 100644 index 0000000000000000000000000000000000000000..bbb2e6d65dd55d5b057cab3d98ced2afe4c63405 GIT binary patch literal 3362 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 Blm7q! literal 0 HcmV?d00001 diff --git a/Public/img/icon/w-等待模式.png b/Public/img/icon/w-等待模式.png new file mode 100644 index 0000000000000000000000000000000000000000..12b9306495f3411863ebec2b63a9af6b48949e86 GIT binary patch literal 5119 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 literal 0 HcmV?d00001 diff --git a/Public/img/icon/正常.png b/Public/img/icon/正常.png new file mode 100644 index 0000000000000000000000000000000000000000..742e4784b2d4fb7bba5053872aec3faa3bd85ddc GIT binary patch literal 2577 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 Z{|7|~fHC!IQ)&PJ002ovPDHLkV1j(v`a1vs literal 0 HcmV?d00001 diff --git a/Public/img/icon/设备故障.png b/Public/img/icon/设备故障.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d84c8e14b5f8d36e6ab0031504b50768fd182e GIT binary patch literal 4657 zcmb7I`#%%@_up)oDVMo3+L&9!gxXwc%w=1-&-INWgg&jg)mSksx5C`sq7ri5+#-c2 zxr9*em0P)s2+0!Z>-{Hue|Vkqc)ZSep4U0&bsmq`Ij=-pYs;fhSttMiI7%d#*&p)m z{}zPrkXE`>&K6UJahW2zQyQazB1MY7q458a@4) zY5+am%BJ=!7n31pgeCmX7?e8CuDU?j2f|P@IS;R2Nm2yvCrH@`OYhIYr~(hNaMVu? zV0WG+i640r*cMDNn?#~Z_ zF|!U3Bmi`M+}X_^gcJa=90hogZn+*nMau zIWsWQ=o`Wq`wcU5&llUpw zz_%u2A#YIiXY;Z4_V(T*!Q&GH`{Wlx1*Wcy!aqzO zN2Id^!>9Xn6YrdK#rb?PC@~y2wyGa~)NNGnjL;jIa;@~=)g;HZgjB~= z3RL6-rULre;E3p+TH*VTE+ZN0IPtdQT-hY?z;EYVV>^x@pj28_0i@g&`l}lB zvMXbgW}Y3WE^Q&@3aJArW@V<%{ra!E3NmN^yxfGbVo=Nt9qvC4wLFT-YVk_bn98T( zL$`KrqT~?v;qmc~PUp|ug4?s^`z&jLikUZP^~a~QtUQoF;yd$`f(X;__;#MxM8JXWq?P)NEw&TBbyr92Bv-m<74s6QNj6nwwj|!8PU6LZcI!lNo(sZ2zQpLx9 zYeag7_bT5JfQ^gIMULQ4=;OdDXXi<8O5ll}kg3Uu9)}axL}8rjcY3Fyl`Ppa&t(xj ziH$2Am)o(jrN5Ih18cAokGiGma4|0%EkZ7w=M{E5UoBq)Bl_t;1RiC#dg(;Trgk$K*?R*17m7&iZy2y^PVU1@Kga}ulq}U#ip#)5ed>%pJ=eORI-h` zb0LECyBtAh}5;~d(X!#?(05aKDS%>#;oM%8_4y@YwD;EQ2zp~@m*-Qqgk3x8VW zucvi`Pg&2yljFDm=Z9eW$J6?2#FK4Lq~a`c6b4I~w}^nY$lIxLT!cB&)JnPIIO;^J zNfV$2(i{c=#z+_XEwFD8+@ddeR)`qlTV%lym}fwEYB4_!{0~Pp;AqNiDKB{+GbwLz zR+<-K#qdds>5w8^PeB8Hx)9LYgU2w)kD^BS65BUlya9xxEOp?x-0ri1(O@*6HKZ)q=b=7JPzw0ILUjpA zWB@js61OOK3mMoqp;42I-qy3!2U6-coQ?H`gK*Z%tvrW@7k=_}vBL7)roj zrRzD`0*UQG9_QR;id9z18T+S?w8yWu|82Ql|0nh1W;TQQ=2VJO54KlTf4=)xBAXhX#yoQMtRs&v*iAAimLs#z2Ar530w#&90S+J^80x<&pmA_+W!vj|CzaxQ68 zj{^BxPVhEd+dNk#S)lUamFPD$7~igD$>0@7K3mGs6#BDv(P}h9uth*?LknY z%LA*^IsnUT)`$=x^rX-D?=^bLoal8iO67+uqmvkA{uvr;5vVhdZDJNh;M~qs_)Diy z+D@n-B6FP$eK>%WMP$Hi1O1Mii^S_eJrqM>-WbB&{XC}7$eUTXHd6KTv-|8j<0tuB zX2=g{d%h5>_TpDdZ}Ybsq`23hu=Pt{)bCsml@LUyEZ1@4j(klm0Q`7u$yJiwJ3j~MMOlPJ_U1h%Oi5eodpCCO2#;b z{rBffOH1F+^ZLE2K*4|b06|~6IR=CVfd~?>#-~_7oP(9J;60@-wDwEiDI`|go)S|9 zg@|w+?Rsj#@$~fG)uX3PZ2IFff?4J1ourYfQY4XLu z)6XJj7LPsn%qH@I(JC2UlIUZb59ZwByWfUaei!?E-)b^s;aCsRzymOkB+BU>xvg@+ zUJSlYj4VIxeDInF+=I8*fb>W{qM9UAF{qCUc7X@cfVOcoJnpqw<8wbuL_Bj(LDTx+ zH6K`~W@uE?=bM1g$^bd!rST$aawAEu1*Q7cU%|dMcN7LUj)3`?5T^cK%nn}?1Ufqx z<&G-CTTI$2J&^^*y|FBBkzD=u6bCQcUg|cFKp~z&>wIT2fWC7d9TW^Ot9h`u5Eq5D z@EP>((_cL!P=m!#+ch8}MU#d{@c*JYsu(veYH}X#arYBaQXQ<OO$K1QenUmn1P^>cb@XSa(qk!u&Uy^xumbZgw0`gWr7cdB^wWajfJ};ns7r>Jrnp-abj&}uD7>WgTLn72ZE`+ zE*#1#dku85?4c*Lm|J$lYMROhCr+k5Yb~I1crjq4-SDWm+mmTJ`n}CtdO`$CU20d> z^w%3@vtfv+O(9mRs$yUjkXjApcaczj(po%K{J&141eTN?@#B&}2qHjKs5PUkEm~zU z)Hry3Wu#CE+O21@J{%YF(?m1UNPkA0;1(APOf-P|duy#3ci=VEwPB{ePQEIYJgVHl z+6GwipjN05rqk>+p7+1AkGw2!*B^0X+&mfdT_6QQ7@1)~Dp4BFfmjG^^^wb0^NdOt zn;|8*6rzWhpIkp=^y_$DY+u{I)EqZX8|+_S>mgmZDx!xc9yeX^yDVB3kukw^=3Bez zBlLXPCOMgu3@5#?ahuc&!S$GvS6TB$7LK?9`N06z%5K85*WrIll>yDa<^~EvUAeR( zHsid2;nVPC*3-mnFdS=24Z{t@-WB{|YcoEfXHKt6XW(^poU6U%Ic91jg%o)heJ4*( z5s4v-{rJX!#JLr!>SyS!CVL4G$QAw~*u!Rx_}jiv-O{KkK(UljmE8F%H3LA!Z2jVM zef$0sus{yFs8l_NIWw}|+Zg0G;-_JPA*W=xr#D5UN8SucJlfG{!$s{xr$agZCCaCQ z4_nTh)cF+4wfm1NMHQZD!K^Xi-AxPb3)mb@mqf>zP?FzDV?W=Ewqh$ z-$(R+%fjYpe7FxXlYy-qcpVNc+*1DGjp4WYl8@2+U1y|7Vh%6I+_Y}yMn760*%sGo zbxe2Up^KMG{D3`Qh>JD7!p3Ye zXh-@-WkqJNwoF1e&VK`HxW42wbV3a^cR0%mgzwV&NMtd1NeJtb*WqLHUM(xKbY6$K z@p#*sk~A1JzQ`BLPQ-dHbfk5bUtw<`ezXdz{a}@TyZ+)>CHbXfFu7mbTG~CVRF2K# zBT1{0-etycrp~$IOkN#u4g_1fYBhcu@vjisV4t+?nkXqz3HWWOcwF+_ui@E6C14Pp zPJceJb|8QhkM>Rvazu_k@gNI!^Q2d|qixG}+a{7|c3K1GJdyF7lylwAVI zLH4-bBIa)Zj(Xtp{Oa9WU`E@2%K@T*(5ZQe=0dUvRmP<{s6m|K2*YR1`E#43Led+&3`s2ulbf4fBf8uC~`rM`h3n{XlP{Z?%;9 z$;})i|L%u|%>V9VQ>1?fPbu^(ezv7N9sDtk`PJNZW&2zPhE9s&7wLH#YgFsucP1~WXxf#4o zg|q{`NYy&;YvbGSWtdAFA{y4#@lF;t{hqnEL1|@kz9IZz5d{wey3}tvWad#oYO&ct zFvi#@WsXCK*ghFv5K6cU|GVrv6RC1P#T7^2$x@?LXkJ zFTHHMY_qPb^n|;8eG^6%hG}bD`&0mivxKtN9a6Fxp#S$q>tA5rkk{Q)JLTxZKOg|n M+}fP)Px|qDe$SRCr$Poe6T=IueG-lJ1e0dsr3wBzZnbl9P;cl97wL$0+xRi&M=I3Pf=M zh`)hu0IEtki770N{?H2+woU!8N#ObU`JdmvfB(}o%@x=ka*Fp3i6ddA9zPSa4fnr;&Xo2&lY|kB{fR??1I|`#hF!ej=+|D$4+J z9v^rocrKTV`FD&qWLZZA#B*3jtMHY+*0$|;&#$L=oZul)-VcYvxmp{)A*g_C$cuom zti!*SYvdALPsPP1gTqyjQCF2+iX?ov!wDTS5{!1R6pv$|xD;;(?1fZ6&wA0(J@O= zfIK}teJk9B3WaBI!7i7}kI;g&e7^`lDj0BeEC!UU0U5!lZWNr4TY=ewk{uv5zTl%_ zrQ~cu$qJBaF_OSxSDGCtSpYJwcK@eon%o!lk`v(A00QMThlNMgfK+$NQC$-~*7yB) z?HMn%fK+!Xk=FZHtJ>{S2S`Tl)ZCemsrpUNjQFdkoNrtYhr^4uEi9@4QD!v=0Gd5- zXEZ_&H<`01bO>uactr=X3`82@FLl;L1t1En#xU@7=7J{d6v64j!7ZuKoDYY?s|IT# z9+0P}r{}h9|0~B+7+P`zA_WYtvM^^^#v{LEX(R!oVl$*@K!mwebY|kLIV&>(hPL&m z{)l(EL;@nnr4m1Ydo|pGg^mxWwk%=;cyWLTaH)zrG-RzOr93Pq(&Z8bNMbld4$xi; zvG;q4t+zOfEe4R&=|r;^Z5N6CQIk=LDVPzIZ%xxgk5weCz>5GRMKDf-P|sd(BbN#k zDUc)ws~Rf z_b(+0Ad!VEF7WdoCRyJ|U`?)F*L_YQg(QGPv>ZuipA-Wcv(Ct%B!MJ4Ad%px?o>ol zMvs8pWwUXTtM=%SLu25XQKp!jTbqj2SMt`wa!;bUO76 z<5=Nf5NhfoIUzyDBQQXi;*JVOYE5RWpV8fd=?w%BrnsX9&;(0+}OuI9( zt2$K15RdF~wY&jA`-pqVM$G&nWiYq_ADxP!y|yJ|P; zIZbj0Pek5U#0wB`W7WkSOu2fL-usrL!sTL^kh}tRFF=r+5w*Ei42cO}h30r(#iA@& z_Fh)R84$2P=tVJyX84o|wwyjy$9PtSB>^uhI4>Uh076G-AvfoBUFTeH3=LVUBXc-R z*Tq8u&T2VZ5hq0jTMuV?1;8Qk4ZB=oaaJ0x25gm^LJwU5L0JzqfjM}_+8TQ)zZVS& zIAC|`>n0#bYBdGsr_%{FDM(R%*LH}G55W`HrZ?jP2ue{z3*Ocq^iF{l&7`d$^tt^U zx3`;E&-{$B*-=eA0u0zUt;i}MNb8|xI|)$uOI!@A*-g{D`|OW0TjptpaD-RZiJr`m zR%FYo*#ZRh{y@2yh}>jf=Mcfov<;qSVzn=6;UJwPJhC zG&3lo6DmL}vg&3n0s?feO12)GK_CKpuC*HJ6B}?sTO6k~Kp=0Rl`dqXpg>^{MaJ$o za6-E=i*ySS6T!3$pcPrPmTQ0@+^Zt3M{GE(80uTww%>uuxS8bv*0rlB)Wo(lX0w2x zW}{S!;wx#CkVnhmedfToy=%`S`;x*E`pN>8SXr``OMpPuKD6w)0`5{y9@qli4&y2& z1>OZ1(4;VHEgt{@S`YDpCE=s`D`~a`ra-A%$)VqZ1eK(i^LXX}fvkNLxG*Rt-U3?@ z@o@;MzjJQZ93TkyN{q5>%|56-SJL7wklT?YBeykXbH4}m_hB-a0|b%1ijx1|BgpA@ zQ1OSfcncN0N^%`Hk`wTM(#7}sr{!TrC zDIkdWL!7cKO)02gR_cTRayw|zQ%k}HvABJwzf(XE@rU@?#sGtgKcu-=R{szRqXrO= zTX`3UOaTdwKcvp4Q!9cp$r9Zw3lM}yK*g!>3Q%KeyID6tK=Ft8l%P=_&}<`Gc~I*E z8rDLPR&xmu#B8HtrXgVh0TJs`0s+x9u893;x5ZK0f|M42Kr&d8T}qHwAlgb!U1!k5 zck_g7K#GY!kXuY715%;|LB$~^@iG7cqE3w&9{Y?i#f@Y@P-$!}X$Yid6xE zQXZ)(-f>(ZY2K!3#Ku{3Yg{19IrQ0B5X5Y%N{EF366`i>SxL7+L3l*QY8nd?oWYXp zYOKsM!FLUJUH2Na`G@JtAg^F(owl(B#UVo`%K#Fb!IJE1FzKM^Vo?^7I;m}JL4XXI zECWcWDOR&UC|aw5jYI8H*0PE|6&+w7+8;nbw5bZvfqE#iC{U1U`lfPh0e}pyWef6E zRSHq0b^{s(v>wzNRmm4?D^YObiME`e08uGKfG&zF0x@&iozfPdTWcY~J0&QS)gsKX zwBx4Yv^G+M5b4cHQ`LF~2w4n(AhI1=XPHQP8>JdhEP2;f%@ZF&9xy<(r2(U8Y{W{y zZ(cGjSDl$e074l&hy|&DM5JM+Ds)!<2IWPbcy3M2l!ZpGR1tg`md)5ug%&gU_J}|dChXN!tkWsssFt#v@#sX>>)007dE1qlVDx>zow74Qr<99nnmZiy7J2wq*REh#7deFQkNa;v~D z)?h(Gvsl%FFhNw|2oo&8#TtV2(1pU9<_#Oi*>7{hp?RN`tGEG^e+9%<*fF20aA2ej z0Hm&@V}=4(3NswnzVBZzm&+N~V!0(D5>N;iOWmP7!U39a-s+LtP|XH>p9_v0SI1q& zjkt^ib|zix%@?l1=6sF|j?%{j0SL*EEXZ@)wzL+q`&05vwOeSoOT!B9i21LRH!Vs^7@t1;lc>_P79aLx(#0-Xwo8z7+Uid|Wa z|0beG$oTFBItY_rXEA3$g56oWrn*S`D0f7FZqnq)mw47d-GLE+Z+xqzPD=9vN4T(N z;u!z|`D`^%-v9(*`mHLeYqgx>4LwGFd+nV4p7dbTU*nK->mZu5L6sevnq=-Tkso?OvzQo%d-$-60+rc0|e-1y_9mK)5je|`NmDt z)Zl#CdO#*2+kL$Q1aWw(4j`*J?5=*my0JB+jQESwTF^CL(uOL~F z7amp9St=+vUrc_?0s?fiYOttE5Dj=hqg$mZI6{*@CECHZbLv7jI__+xP z*otft8!W+EK-LlfX0DuW;n@TPY(<=?&3c4qI!BX``R|h6A?Q2Kz*Tc+J#+$Ov?6q# zA#^2p@cT-8ndDRvNS?oc|Nh#xEyZ?o@g2Qrlio!8-gVuZuOj98Jm^5wARgCEpH6@< zSdn4__8t4&D0X`*{W>M2YvmGqm`TPN5M*kNDlhGlIY2B|tmOp<=FZlG^wb#;1}joj zzz&)Li-ZIuyTK^8a9WLo=2<94lc)M8U3*bzGb2dS1;E5jK zQ4U4KaA?=cC-&G42*8(~>Uy?r1B1mivdezal|gp9&L(-eSY~t>8lPo60^AbuU_gC+ zX>Ar5?3V6M3he@94A@coVa(WN=QeqiH5Y zE^N*9+c)6UAUlS*!z-;jmCwDnK{}I+f?X>kXBZ$%SuJYk?i8K- z9LDn`=Q@aHxfp3P!2$I=V1SIS7UbgV8Ff_&31^_LJwRuIWA}pK(i8~=gfSjb>uxbA z0?dWrv7PIsGRXuMcR;gPQ&DhbB*uEwWw$t7Pp#I2SvOcF4Y&m%MdnZn3q-Au&=viN zkILN!+&aOP@nivnIUX6@Ep3a5h_o*%b%~(Vrwl~j*XrZ6sBD0YsbAEcT66MIcUC)K z7Cj#hhgXd^o^U2A#`TWi#lSWASOH-U+J}B=n^mnFO=$Aix+O;S-ZX|?xl>(ccQ@Gq zi2;d5m&=OP=-QtzBkXkD4}IP*mkV9{qw>QXj7OaqqW}^Ml6pN(dY-sls`_@7jvpJG=%g>hLncqv_8YC7FBfyB;7+lBnmIagklFiXd(3biyZQHtRulJEb z=(8eSs%fXh10v9x%qhmr!t{NAO_e&H03pG3T7pQdOQjMJ)98e$;61Y?L1X^B6FA4? z@fx~7X+uDb8eb(%R$}Y$)t)}Uza!nHQVoa|z{l7T3|Edxf#z_OaoOhTGfJ;Q`8Ncn z?jC_*0^-&JuJT7~BF(Sn>aON;Rc8X#0-_`~(X80PZP(^b&2?BcAd^g24sKVlQVJG@PV?m~hBV>P(P<@6qD_bzK z2gHs~#*>RR;|1elIGy=+xmbBfs6*;;cmxS*-1GpMOHw z`G~#U2>spwMZHVxuNaHAAWPa*7%at|p!AtVDj*xunjA8s;9k2cW`Jl)$U^zRP+hE0 zY5je@oH>=J0hkIzz_?cn5+FSKsyUz0w(W3oZ!9haIK$bKzVFR@MO43IByd<@U$20` zMEO{d4Nu?qpGJtxgZ5g?^xVhXS&`xY=-`!A(>vl27NZE%7yW;GK~?`9WUx&D0000< KMNUMnLSTYMIz^iR literal 0 HcmV?d00001 diff --git a/Public/img/功能检查.png b/Public/img/功能检查.png new file mode 100644 index 0000000000000000000000000000000000000000..8a44269055d940e4870494ce8a2d0cd993311661 GIT binary patch literal 1796 zcmeH{`BM@I6vxq26iYKHvTU_TMch#kmGVr%0uS;c&Ad>%95TcMSrxBc@3LZRL6EdO z@=jS1ORX$#CC@gBGR1VwbTvHJYwef)asPsSGvD`}_xa_`eCN%}bR(SE13Cl(004XN zIIPEx<9C#%ylbbIXnN=Fm|UdC83#bMNPBu`P`GUGY7YR^=BjRx6afHvBR3Z>#~uEE z{YL^yN=iT=P+3_S1OkDf4D75@q2SI(0ss(=?~?1*m)QXTyH@a6d#@{)S=Lktm%!y*p<%j7 zDU17*^}rakQoyM^Iqcpd1!di4&0^5tgJTX38WxE^M9$eTKZw~MtZiis9aGe^xHE|-Ss?kp-E+%tr)4wbPTvFWH->jUT z9@VPBDwJfSz*1;0NS$J0T^VMbtxKIa(<%!!19Es{Q9%YJMUnxq28i-dC>K!d!J&n&z&^l)BPKHB{SA+?nOeQV*PQ}&6izxU%h%w zQMLA?^{U-|hK$P-Ro*>#VZ@77O)j}WFZU0O?}Y$~y_LKr__qqbZI)r39QD+#Snu{d z!xI7t{BhKl3nJ05=33viOSsgxEAxHrQZg_B7gD7#KD^b2?Noca05i2Yu0dx3t*apU zuA81B%og|qCT~%NpUpI*t>9ox8`?={87iKAfX%pL`PyCS#$`bdPRuB|ZJR1H{nDY2 z@;2U{uU`W;;X2p4nnW%8S3JN zJii-RN9nA?HG zlk^xj>EC8u!D*tf>j-Y{jNO%3OB#RGsZ?P6?ZMsWqkkjnmYu`fSGjWQL(e4m@%uXL ztkJJ#2^Z{+Z5EFu8lR>!u0k}I->Wy?#nI^g;1)aX8k_SiZqt`gmA_$2qb@9sQq%!L#Eny;Bdd0T*{s(FrSx{A+IWWi1Ckhrvx4>3HDj$*bKmyL+d$tzC7H(zNT; zm*~bZj%407d{rME&ph1HwP$qVUmUBNNBzVZY>HqaYvf+hnlwmSZ#=(0YrG=?TkQ~( F@(&0~&W!*7 literal 0 HcmV?d00001 diff --git a/Public/img/方向圆-向上.png b/Public/img/方向圆-向上.png new file mode 100644 index 0000000000000000000000000000000000000000..4637185baa6ee6af822cad0f9af88e0f54a1a864 GIT binary patch literal 4719 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 literal 0 HcmV?d00001 diff --git a/Public/img/方向圆-向下.png b/Public/img/方向圆-向下.png new file mode 100644 index 0000000000000000000000000000000000000000..15bcd33bf4f5f74a45912cee8b989dcb896cbf40 GIT binary patch literal 4639 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 Q#{d8T07*qoM6N<$f&#)x*#H0l literal 0 HcmV?d00001 diff --git a/Public/img/方向圆-向左.png b/Public/img/方向圆-向左.png new file mode 100644 index 0000000000000000000000000000000000000000..726bcc3159f0ba450930a4bc615714692fa3f31d GIT binary patch literal 4578 zcmV<85gqP{P)Px`oJmAMRCr$PT?>}%G!D&M39u4|l{{Fwb zU#4Ao-on+ezkUw+uN5fr?s7hog6Q|pW(pqt|5fuC?mh&FU#031zF(F_z#u=ZUTfe8 zXntvRqOH!00I@YAfKc!7<0d?^d$-p@KqH=oUIx$&0kSV71;q$}u*^UJBcA2gPd;O{ zpXzf0xSzjy3ZYA14S>n55>yBgdw-=Agz$}9j;Z?QJC8pfp{ z*w!P~K*+l9y1*#EOWIlgR(k_bt|B4W(AUTSQGW4rMGdNEJJvco&l1@GlZ+~n8iD4vNoTt zfzl&DGQz2@m1Z&W0a8N5yV<3xn{nM6l#u!6 zH?UR#QW8>0s#Xrv)j0oD*VOtReMp_P2oMRWehb*jbSF&%GPaR6` zM8Uyu>I&1x?-32VnhUvF0!So<+vKi;+tKhX1t<~?c)UqdAZZ045i%}ZL(co~YFh$P zZ_-3m&;mfD@aH{#-GuPkw#(*b7uf`F*Yn)~5%=pkfyZUM<10P%uD-0MhB^9^qI zuH`iklB)sY1&3s*T6!6ROZ#jLNx+-lzckdo5+ELMkc>mNHB2MnC4V|rb6LoJ6+k?$ zl;Ch!%0NxM8Lmq}as@y{7bMl*7hDSGWU$e)Csy&@p3m~416~RGp97(_fk}8K+YXHQPu_8DK z4od=_Bu{!~D;ppl-a&9!roqou0w_q*O9a^fkzx<>a7;SVX-mUP0F6viv!R&)L3u}& zSaEps-~vSg=(9s<$5FBX;&Fku99yP+4Iu$f`Zpy?$pDBa(?H%agq_~H2-MzEQok7h zK|`w)MBl0!-nA1>j^=l(W zPphME$O-Y_2tZI`&d{og-9v+}bu`09g+?@Pn~VSiIZhHnE2MfhvLvv_4Z|_Gb+d*( zuM*XG0fNMPA~QEq8xnM{Q?Wvg(fJ@+Ky=B$3lJo&JHu|(8i>%8r^`56TO=?aWCM4F zoF0H6HPCWZvi_*;f)>Z=7RXf}PL@E9|~J&LN96$Cc=km#nhmc!^C9!Vm> zUIYaQa#IrXYvG8H((Q~!53zK;h-{$E90dsCJxI*20f>B$S`Ywp#w*m-Pkvo?p;zi6&0|5wfBgkEKF7Ugjk8D)iInEsRBJwijV*v!+v8-|K zHm=_9j~)!2iHuu1MKfBbUc@qNL@~1vKT9DsK9BMZdh`!%6nha1AV^`*8l#5c%rGXp z1FmH;E8jS>2c)`w%Ae1S8$sXbIrY1Mh=#UXaEyL(H=++D3Oe+-X8=LSxhO;s$SY3* zk>a08HuI*}-AITRIh5ZSK&j;Raehahq0D>G$WOx-iDN! zr1-}=lV8qO4EQwtL7ZbwS_!WV3MQ@28N^W-6GfRKOW*bTDLkc{WZIx-5v zL!R}JH9*KeBI17SgKRS78|88?9l_!u&(jKPfLQ#41pQbo5xya#vG`YN>aqS74|x)G z1qc!rkf84?gT=p?k>1%0<{=({kf6V-6cIG}#+^_&-qeIroLvtdq5!dCXTJC9U6hua z-V;8<)ONsP@emh4sMuGF`0+)q^mDg()vW###KsWP5chD*|{# zO$rbzgT>tsdu(&7WQL|!n>~I%0tAD=(OmK8zokrIq4+d3m)3keO;BmT<{SED81Txdo6% z>RvsF6=Tns>OE6)1SB#ZJ#jnWu~NJ)fXK3DO!Zpov^JK#{`AI{RImBmO!3Mi4r=ts z>u+XF^;+s8FR>)l-scEGf7rVM1WENWJUCW#6eN67@gDG4{Nouht-~e~^)h8ecnP0W zER%V(H^e`-yuym7Nz^fQSaM`h5tC!hRu=zw9zI=r5b}^bl_0X*-i;4o<;nkSB!quF zUsSRN2zf}Zf}*^H@8QbT!*(#4@Isyp8te66#y^zGnc5D_E{nEC=tKC;O9UWmu+!4bp zzmkr6M0p8|ikJ=%d*1z;k0XFE%)$hp*^0a*Q<|@1S&1iU{gS=X?q?4{S%Zq37u3!C zwv%j?MnEESATK%38p`S2v+MB9m}dY%+!9~8nGKPT@gn4%^{IVbAmse;Thz_~f`nN- zdQt}R+vTio}Zi(CU4L>Jqc%vw|| z_8tfa@o*6q4zB?T$-6CQ#Ct%SI^scOI%zkw*Txor1Oy}!a*1BhYbIWjMhj4Ypt}~i z2x_k7?IPrThO8s9nZwZ&3J`jca)Yilf|tCHzKJ1q4>)<@0SJ=v6(eAEy%rRX$3;Cn zY#7%sA?1!p)g1O7u7;n}N8A_BXr<`dJ%|O8(KjwM!{^#0JRU?eW+_3nYUY>S>SqT; z0!O@L27MsJ9Lij+1?>e0%0;9d)4qsF*J-onB{P5niEKhP83Bmgs0v!^*vhn{O2{EV zk&SBf3n>bQHi{@fP{Qtt_eR$u*H=XXXcjLN(L@0vD@8H}BXI=sj4`C0*e|6={(L0v_!h>arMTOB)fC!2u)Dl-`UF0K{ zg!nls0hD(XZ_K3tkp-cyj(h}FKii#20OcJrMu?cNZ=L}VPpIWC)X-KafsF)^lx_+* zipa~3+K{Z4bPHz`Xe!f70OcLUp_NKH%Y$gBB@2*{%eu%%ED7=Rtprfsks76B0>r~d zq%A>05TFu3kCLQ?Ry90`j_E-MgO(3eGP^IIE)`o152ADOERY~6)#OptnLPg_eEzjy$Nt0D7>$2(J{WPx5!B7F#wOHHHd z&CpZ1I*H3T$9C0s0YpLa_0#ZCZLpw-N~+Cvo)Z?ggX0bkvQ?XxxT~w>cks0dfU{Y7 zLn;~T_GgFg^dM_tMuaDBS5m>^Rd}^4fk-&rOi0}dKtv!BkO(+~}28kj)Iw2HE^#B0d&K**!l>pM01 zY*32;QIL4QgHMIcOjntKM|(%PhTQMAG_JMSRso_Q@uq>-AYrD<(tgh8kxb-#Z^Sur}S{&c=-fkW7AZl0*!bXjlpYyXAK0IhpbQkhUh=qW}262%m9$J5r{Xr0w{Zi zr`~2wT=nn>WJyWcO0zz676o$+Q5X`9dLa|-|qk!nKxarqUat{KeT%cNa(88RiW3Nud zY8qK+IR~_jR>@uU4WYdi^g!P}wy84*}C-vHaeP8vp)cMRPqNGQ?@2q@Cc3^D`K-6aD^ zmvp}u?CrkyzVG{ep7;Cn^QS)?xHzvf*16WPj&-bXEe$1-tJkh#VPTP|D9b;@!omS# zVPQ)X-~rzu9Y#I?zFcv7s3eQ^rR(|<@Bw5gqb`GmRUAun@(dUFO!!jSzzKM?>Ehp& z7W+IiEUeKf6?qvQcjLAC!{K51iVeTB$l8OMFJ8y^!!?$v+iQdMcIgcZd%cnxpWhGJ ztu@>8+pMVh6xg`cqE?Tzm06-=)xhrakK3tLoGn)6 zAdLk%_^$^GA%RH$%ip;8c`!W)@An9Jyd5l%-y=ZupW(r;{4q4};8kG);(xs=`TxhS z(hWn7e0_!k93=23BkRrcV8We}hLAtFxH8CGhL zRV%IYm~SdhXoGY21oaRZx6CT&U577K+u`#v(VHRhJ)Q5?=}hJ=fM4zTxkln!O@C4% zifZdzUe|k#cy9WX3d}3APHictqZ2Vx*>H0uSonRA-H`MD^wJ2Vewk;%-Tl4c5e~W? z0UZGyshm-fx>F|AVIMZ8_XO4*N045K*2?2?OdEOr`v6|K9D8IK*F-$2;FG8|$`Z+yvg-d{THeH|9V&9IYK-7=$hm5rFeT(?bOKf635p3u&npF90bc+S10QR z)g#T;!m3@1t)HWoVITFPX^KvsYlR&w7l4n%7@zEK9qsDQJ68#zrWnNw+m_77^kbG) zhsM=K!$^d4!n;M?U0yvarvq2<NX+MF6u?qFDRB?0?uWp#Vh#fViU(>17dQ!~QgQ?+gksbH~ z*umhqrD|drS&ljduU&(7VcKohydNJ1pTK$oQAR>U`Qc|j+;p3ce~LHstK#6qGCbZP zDt5&2t%i%(lbtwbfAWn^DUmPqoJMSC2!vz4Jmw8P=o`=EzV+&Rtu{VF(s!Mnwc$Xv zOYN<$AzY?N_G2ZDL-?&ct{qo_-K*neA^WGX#-U|N8=HMdqgAiN=mLpwwoao(On@}ohT_@@ z+w06uvjJULkJ3&R2dz#@N)8{%O3!Ui)qys$2AFuwEy!k-w!($=|43r6+TKG7h`w7N zR;_1_6u0CjRebK{b-KffIp#|-CA>lDA-epNZcucvwq)!o@xwtQY@+Cjh3BkunkaqP#iR1P1Zy?uqC=ce9Niake$^4w%zHdJS0xp8CcYLx1FY75ub zj4`eHPhtaW)ws-I&x`C};*}b(9}d|OzJLP&<^^15IMlAJsi<2B5ueFWU-M>)AH|t| zF;W3k=X`+l1uvv(j%EPoacIrt>FNW)h14~hg(1S<_7wf?^vON#>yj}4yC)UVHuRWq zC%mvLIErE19p*}E)T)69Q{Vf--*}~@iTxB4()mKH5yd+d@bJ^6arv!Zl?*StR`cGo z|FK77nBmH4{6H6OcFqzf?i6=jsb{`wQ5g-2j#bGc1#LSK;h|pbAyTv_YrS5jVC8vI zgn^Aty965|*_MfcfB!y4(Bi4`kHE@l13#(Tn`pDD5T#r>nEx+r zU|VU(_}?)1&5HePC+2qB=?KMe(0A-Td|k-F4dBhTbm89d(EW31okeW91VY?kF4}Kv z{aS3e*z9yx+ZS8+UBJ_)F2QGk#w<=FYZ^C%64wA6z*_Ot<|zxMiLCrKFF6&?eF_S@ zY{IB$QT!GA^@J4*vSDwQE4||k1W^ZPr;dZPVCXGFF5M|tA`spU=8G-9>%%i%JnH}3 z6njMx7{b~eUO8A0Mw*VMaZj)j^BMZ%u-tjRIq22a{)$-OR?r4_C?!YYpI0CfdfY&Q zx1zDPJ8aXZqVpWjbha}z^t9EZ|29Gy1QsUpHIV8ZuAIGlvaDBc`{n==Bz*(2bGnHA zExleV%T!$*w^@{7C{py?llIR!X)mB%Y()Mtnw`#~Dx|wvvJ}KoD=Yo|E~F>UXR_!Z zN^vvg77m(^_w6+Op8QvV$?0fJB75Dr91JC$;s)G*8Q)LEwb^UqEnKPccR(Qz&h7`$ zhxZgoW07-UpZx0OQ)RfbHN$wT4;zj=6vmM46elm#Na zlqWVog3X?ia}3;6V0*;6VFwtb=E>}M^OgeqU2rmA*UsJyQG_(X_r_OyRO$5uuZ3yH zHk|7eu3`t`*iK#e;=_;4>l%A)>3Ca&xk@x3#XVyAhY$`l_GH7{w9rTS0BE!3QLDfs zogkBMBVF>RiBF&;GKr|RqN0WXB-VWPvX&@8l+9&CRGdCB0fi)v^p_+f2~eSuun_ZV zmoljB;fxZfQvYM03=D-L1L5J1)iG?gll)SRo=h!V#+KuzWC+Fk7GS|!Wf(_YrjgRC zylPqH&bGsQBez@R!+jh!O9f0R7{?wke<>Ya(^p&%`}~n#Zxcj$mRfeFfzsEefmrLDRNC}9wB=bpKvgaofs2K9LXA>8$=v7SIXamAgbi<)}7p#tPqKo?e zOIz_kR{PgiEvT|A`A-b+?l{eKM}QEmarXl=rBY@#+8N6{ya0!4yLGvZW5VExQc|wa z$nZvnv;imZ8F8>=DMg1yPeUruBqPvCZ3h8J<)WkXP4p-K1OzIBgBB^MNi^x(LRPe8Ktc(~_>$iW{Wb zy^eEl74IZP+23Ph{SoeOY;TY}aomcarfd|dCSix{80K_@7I!WP54e_jqf8rKYB%H= zyyDmzud?~`Qx;SpBI4au_QM$VWtAtpA}d=uRm6Ni zq8h;e{rz;4ZSsV*M^iz9k0`jdGLgxjJLN%HvWSl=jvU((3eKvDJj8EcJ@(yf-mH$U z2WrYuFa$pv;3NLnoEHH|EsQK7(c3b7lm%ZIN{X68#!=vW2pw9SUdsHi=+mHGY@fwF zljEetN^J#f_L|O{xR0=0u&|r@SRl*M`Erw1_lE!G%l`!{Xc6y(0vmzP{z$9@g~3d_ z0S|}28y?^){$}coB-nvZ(?Xvd2XDaq&!mCJ$-$$yC;tKFDh@7Onr>uh9SLwl$iW#U ze|M9AfAhe|WGf5gM-m7dX9pj+m4V3bIZOWp189Leu5LmE#0Q*kB-SbXe_Y6)!_mP* z>tqlazfH8v=Z8U!Z>9U<$8yZkr;V`fW&|sLwVyWI&&Pq@68kZtD24qFy4iFi9%JKQ znFl-Dr>k4lStf%)RUICd;tWX*WqiW?rt43UM-Mq|X5&KC>y{^s6*WD1^^ERT>EBs1 z$~TqTc+l&st!4{kkG>SZf}vV2c?^6DVj>JapIaG(ns-{&8=IzB% zCfzQ<4F0Toxmf(-g$)a2f(2m%eMAJmf*>Fu?hybs`469AyYyohVOe(uzk6IUj9LsG z{)%J$^l%)dU@Tjz<6UyxGO{%$>p<^oy*-N=s~DRy?!yFc-w2O*9B=A$C>QCpFUVy} z?`MOHXZ(ohKZhPXw}0PY6jf)*BknE&?OSWHd%QM&!rO#xFt5 zi)v1*h>{`)yCMac|9yf>)7H7SXtLL#jim3?XA2FD%NyE8DynP_&6pYRsmkb>w~geD z`l>A)1x#kKKq1e_!K=R{0Py_h?XJraVfbZzw89)l;kI9bV@{P>5apbLPe+z2(mWp# z>NTprm{BjkxWI;qi;3#wKs5&gGkLMPZgn}%z?eW?4((qS=hi9W(8cI9DpS(hbJ}M> zR`_MShRorav=L@Y3mAbiHj>n&spTUTIoP2|Zfa8%8-C>oCm#V~_P!-9h;%~BMWT~= z7)Gv?EJZbVHRvOjgi&ZLhZz|o_Y#aOi^x*(l?EiN#SVuO{HB8zZMjj;Eh2H2?7pxu zi#pjpyE%3DRHt|@fZ~^%wC{}&r%)0Kd#J-FeUF7TOp~5P=~j1p%gS*3o>qOH? zOB1o8SpAA?)T%Q`8@X3i^;CydZLS4N+w__C69WD& zI!gb4BL1vy#Je-W zWHgu^J)ZRRR>OE%_-7)<4w!#i*6%BIyFL)%H}phs89u*?9Kln(U-fX}aNy?UvS%=| zz@~kxq{A*&iB;!jfnaolkOvOqBE^73$4aKFN6EMytPZ818RX7yRj8$Y8;bmv!}N(! z8s;3|A4_?@qj}D8w&a(_hv%^3^b2~vz81eX{@Rb?+>IC!dnONfoU->TBQ{o^_L zMCjo7;SwBEhN?Wvda%=m_y1)ILwfM7wWD2=u5|oJ#>xpKS7XL;VZBY1`~H#j$Pp_G zI+%m#-}(+m3Et%V^h@(Si# z6FRs{0Tpa705XYZO3^4&fQ>ZdR0v=PTJZloIph#o!kzy$N*rf8etn?;$Ou9*igqmkCTA7>1gxa z*u1F#xYe?feEA7UWNIh#Nve4*sH39GE-u62~Ov#~3~)pz6c3 z=6_668U{{$1na?>bpM&<*&#lAyV!ostGFfrd4o{{25K*}gy1o53kV&aFZ7=x*3bdt z#EJ<(zVe4xV}ZOQ89wan6Y zMSmic79zn~p~ceAnxBB;;T8^Hh4z>niXBJd_lTL|VTf zQs~q@i4-80n7gIGf_*kFNakf85ZX|VLTF;MAJp3Y5r!Be=tWs72qUgw;y?~Fg0tB0 znWl2UTH(m=-xOeT9^a2A4ejEltAE59_MF>PufHf>UnhL#BLjOA<0}4!lJKFjRTdkU z$jO>_F)Wah`UNd2?rN9G|2lToIJW6bnA04Prq9vtNO?6+b0r$xy;&$g5Y@>H9JXfB@mH4oyT+;8kIv$nn}X`W*5@1gO?Y#oCQ*{Sb)1OP32(e>DZN)wd~vwORI17d>6ZYZTVjqwbVa2H+SGIj^f=Q=+RITXB#?LWv9oTgI~Xw?NiS8|Ccwf4BwcBt{)0YALg7R{CZYsfO}JiGWP1qVo&o2-~RcG zN6jRQgBonvl3q>#3Z(`&Mk(Dke2oVR;UxzT23a$Q5nW zchw%eiiQ7qvI88sIWtBCACZQc_1=P0wAkS_QE@6U&-3la9ZRcG^Fr#TKb*$D`eC7Y z6YKwFUJ6dQc%2r`wBQE)FsV64DlVTog|=zLd2OlbH~Exem~XZkkOuROlv-*AXu7Q> zFtRDj3eMu8L}Ub|jpA7NCBlfv=;%<*+MO!LqEl{28ORuFK@c^X z+do}{42z7uaTvR|AQU*W0X=>?2Ho_lc^a{oeWt#e%aIpTRihd>b_L)77y({lMjX7P z)lqe&SY3;lJc%QWD3+csfyKdm95if9fa1C@l4^ByAomJN&CJkW5SloT58!NcUNZiBxzhCEYY`F*` zk>?w?Ae5zq4`4yE>?2Z6hHo?ykzudN+2?WoJR=rJUuLoc;D$56Ec`0ubWH#5Fz1ve zl0Q@!euyN>3PeII1vsWeLae?^1yZaloX76>5UfZxdX|9alG@U5Tpa%j>0 z$xg0{jPt{zv~bMl(r$v4c14($xIgj+;c2#eYmrYukxR-Vb6Y9TBQhPvWySXDm`*%` zsGm*cWGGw*m8K{nPzc$@M&e;ts$gQ33YBj%C;5JhicCQ!vyondsJ)NV zcg;IEb@wqi{Q;P*$fcV%KYlkRfo(cjACLNJ{lzRE@WO=*Ug0AWK2P+aA47PA|qUoqXZnmQ)}V(n>n+Z_l#dK)Uo8ck1?7W_nGt) z0^!=x8{c$4EBFFXjb3L>*bp_VU@BS!EQ9$I084WI5O? zs6t1O!&>m-lav`yh!VA>&pq_5u^pB%XwFqK zALelRhgsZ~Xk>Y;2__DnbR8YXvb}+|oo|h~>hmD(F=)P-^FffX!sC~PB~d3*<@h=8 zv*a98@rC&-u;nPZDwj4}efJ#tM1FY_CXrAfEN7Fct&M8iafXepzoDz&xe{y7D+x#2A${d`Ow#Y=457$OI&Bi8_9$-IqgU`GsCk#@PIGht;(!`6L6Cj&MqYI9O zLl0Hbsc9z!an}Ox={~rb{h{t)@0rQP8q5ah2Hj-yyv(@HgCvTwoWk~4D|;1EjOl0lJN+j;tvM z0qe4r3cVc)@2Xf>Ao<9p#x?Dqd}_;|A9nCsu|g)`$gho>Hk9G7U)Lq;(arj`?6bzR zi%=94As3T5mXlSqzsAb@_L3*Gxsr zSEI1j4qEj%@6L-w$Q9mKDBg*Uw2RL&5H6K^kaBO0;d${A2&6a>K?z1Rly8Ka>ltxf zVEqasxAGC;Gm)*%`uLGKaFrZ%@oXZJ$7jK$*Q1HbKJr0R4%5~v(M7tyJI`AnJWiZ& zc|}gio%1(l63OW%z#^4bfjLhd zP1jRiOAIN%4tDLrB^s(&HphcrV|lG{xlS!%%SoMcyzsg|w6t|~oU1e@5HO+Pu_&Ie zI$p0iVq59Jk0i7=!ikF1PK{@Gr(oTPAz?S1o&I#*_ zzsr+nDcayd7qk5x#}j1TzhZFYP1bnUA~rXCk0H`0uQ=H0(C> z7atb>Fx6`oMn)jT_}`!y2m)j$zb=?W?7{SKqjeV(7D99g133U4|43(1!J&~vCbRLh z4CI@QEvqB8zkph|&|BO!Jb*x$otp^MU`MPXDowED#{i0Qf9&uz@se1P9>_ zApd`{tpB%1UqLIT8~u^~P!I_3@AvY*15P43IDB~En*jEoyPZA%KO{}Kpb$XDfdBvf z(f@Xae`7Je3q-^w$iTj~Z);g2Hs3w@f7oY$IG{d#wZ9%rgsM?-3rEwv7nqXRzFoZY zP5YPV1+8bFdPlABy4&ZG+qMxSm9BgY$G3s)Grs_;AjSWI^-%C5i1M+XrfUCErL&Xf zmv-=SVi2<}ZcjHo;Z;c<&y0<`xm!>2H=~ zP83C!t4_1sbypqWYS>b)2VzFO*Ah$`?^%ZX6zG+@WC3Z+&B*^P_0Y~i>buU*W9n7; z&EjD_PxmzHR6E3h<Bs9WNy7cSM4mxZ{D{L6EI@df_LCuV=W-=nzA}sEXS3>f2-a(>Vo+k zm8aWbPARIEEv#N4t>^-f>6Ihg%j>z`7EUs7=l~cVnpZh#3ZZ3m+k;OW0=&R;C{l30 zOUZ~B$RPRoodJT~8{phhc1E1DmS)L%JL#h)BWWYd>0-F-}zK5R!RZBaBCMq7I14C8#R-dlkn|Pcri&-jb(B2c9*LN zKRY)ctnxX|e++#EP9ZuRT9*WM2?m&EiIj3kylLo_s{Ptg^&IeVPeocSJ>N7;iqKx71Xi0o!DQ2lRR(EzM@=E+DsG$NaZ}) zJa7jsQ3u0KK-p&KqT&XWZE_K3aIk}$fVi^A>x;_Dmv?n369b1M9+$*w# zQov`2DEGLxb6Ffdp|nUHBOo5jslcAiSyD9#=gq?xRfk?10*LjP3u0XrU-R5p-24-G z7wPEw)#jSz>FndJ)^%p8;vZIqMit&AvC)BqW0A2QfDtYk30KnX2!OI}!5D87eVEQV0j1PbkH?g#dYjW4r8gu*&uFR?SW`5tx&gLhJ9i17%onhwcMr49PAWxHU{1_DAk zBJNIeDg!Nbpnmtr`|H{^P*ADGGzOdO{uCJP`b_m-N@rG2GmkTu5`*jXXn6RW>}`FG zjK+1x$5o%yy=3ClE`H%?!|!M1kZ#FO4HV594*9`_;%{fIU$oPLoxOD4{17gsXy$u3 zBSeWeQA$s|Ck#HD?#q>i_55b^uBUVI!~+th67h8XF0PV{cN2#wAp?6eU^|XS6WrBd zc<-TxlBXI*_p9}y8Z0xxF6TlHz3eNf1@OIS&*uT>$--1_Li9ymhaM zeS5+?AUO#N**{id=CtI?-;@?r;>E=q-86Ja(P7N+?CZ2~@8&y@R`YVf8LxK9;$xJk zeDCfxX}9&geFe4KKSja5{+<`8tWp@_KMwGg*oYCG8wN@;FB056T0^U$RL?Jqs;?G* zV)~LQ%$vWTEB`9ZcueP6@%Qpeka)y0#RN4jet7DCg*Pmco|YvKnr zVD3G9$`5onK+OtidEjedU$nKmSDkP8%7j>N3~9sYKa0)Ziqyvgwa2~zgm)A` z5RSMXX`5iAb___5q`0qTS#lUzKrFm4=Im>aI*md0u@5U%dwqqbJs)FxfD}JN9~F#e z4H}wLwsTfy__1y&?V4U2-dtqT{Nl6%!ebK6Uj$UEcmQtxqo&_~>iKEk)M23m-FRbi zw8Km%w+&nFeu~UutM?78o$);E5(|h8Zb&Q_L_$`EwVg!0;ai2-6F$gyE3R3ay2tqs zdu+9Tb_5H3A$@+;b>Fxlz8(8N1&*!0J}0C5n7XYZan6V@*rrPW2lb)C`n#wQ+VZ;C zEI$NO%AisLQY2O+PEcQwEK9Q3`LQ2NwSb|iI0e-o+3$R)F2=99r&`do;YV(=OBSJ|)96)|{%(UGzN{#2^EZlxFahou%L@*1mENyF-?10> zGJXw^UgLon*>tDfZ#+M;Q#gFAkp8`GXJxCJ0d*(#R$`ILoS5`~k*Ve!Ds&qG`+nOg zvx77CB@K9E$}xMywdt-%HSTG5qV*R_>y0#U0U-KT4McveEIIY`0|e4ynr0JQsH>w( z4ymmFMb}AfJ*A<9NU54D@ zSH>DWV-1{=F65h(3{%r=Lx}Ut5g=KiTzBP@{j7BFjojs5b}fE`pJSnP?z8!#ISq(W z276Ji=4lDGk_*`nP{cTui;ap_V)1V^YksmCsZ_GD9p3-UEc%#J-~p z|I}Fvb!>@)QG0Y2;R)H@mH>t3_q%c!e)Ns+VWKX&>k4CHN~3_NTuPJP2= zkiG9bIT-b;I4RK3czPky)h`mq zYhA+s)M7Iid7$&(lLE?XUzeM?Nv(!<#}iH{B>@u3bpC6+DBq$jE-Xl5GN{XU@wjotU$-NkUfGTNsYZ_^XFP}4yxAf$F8?%m>XUe9ylKE+E{-7 zeG@*iOB%8@>~#@M9&tb#4s}+ik7TR-$~;8JCVo~|B%6OBRMb6>t(aGYo(Qc}--65Z zsNqfW2U`lY&6gV5)7lfCmW~LyTs0IB`%DS0k6eh*_PejrQ8UXTGKzcJR5(r+w<~+; zi5sRQHEsOXZf`Z=_m5}@ko>6{zR4gauy~@Cs0Uj$a!eRGpP?%D$?mM}-4n5|K;Lpw zfr#y%TN&Ez3<}hzwNrzydT!Rb4GF@o( z*Q41chyu=%O>)@oo_0oOEnI}zKGMJ<6}EbAeDam^*j2xbPc&jvb$Pa-kaG1X5jPfA^il!wRC`*COt&`e&5D`F%0ly z$<=uxI#N2CHJsO`ELBHHyYT+plzd@l^CUZFRwo+p^tv&3MZM?MS}1TPJwIn{1=|a$ zh$GLKZQG;SP9E+~K(X10j)t%+FZv6jbqR<)UnQ^aF2p_2;>%0h!AIGXLt^lzs^AP?y$uNHgy8qpHvBN$n)CK?z_ZbFQC8#B zynHBg{oZhgXN*DD@IXy~{1ge`(b;pCyoh!l=rYRJ)CAzaZKJKOkdtdN3> z#}xai#glLdOVH$IsRs8AQP@aAZ%JiHB)m+`^v5n$)2;xSDwlJ_ZNy1X_fDuLDd9lo z{T;E^$=W)NiN3u$QG-=uiI7P;?OgXyt{;UlM`p(f-$gWR*OM?Y_f!yOwM;Jy-ADDA z47Bj=9P_UPK=Io$y;dS6O)jTQzp_TYX$+kP-VbTOYyny>J2OHUcONEclE? zFd^|#*i=Ufsl^5KWvZWnIrLArgt#d0EwKSInrX4e#1c#u*iBSaO3AGnERea1MqgQY zCQ3;wO?A_IN1jhPZ>}WV^vF2ZYE`Twyz(+eHuwJJ5@b{GT>cwJ!Q`3~DdCa87f`BRl&95rqh}~o_CDzy=P7w7m>D(T1@^xlPQX)Oz zwCxo4T=e+I?Fc)l!R~bc3jm!eFV^%@p^v;;7fVNh9u0{# z*7YDGODfb(kGs_323X49o%G??Xu-h8gOpr%@;-qCRAG6Ij}r;^UWZ(>8rKW;G2PHT zwuJ2YHG}|5(%34|00oNNYA+D6e{-ih_7&;c)IKkOZ^nHdjn!?A>Am}72@Nf(gKyzU z9i{E_HD*w&h?X6C;+*s@a&Z3VPd=aaw1#0&?6xJhQ#WpajRzCuSkE+9+3it%1i@vVhO^@&rtP6F|=-o!@`b%z4@@G{|Md|1SB|x#X!r zk8kOasy;=$M(HE8z}+02_PyD!;a0bMlH6zmsD0H)M-no#oB#kBP7`8%S+C5 zvoRj$bLG_g#vXi?v2^M?nd#nH3S~v4$03o(Mdz479^?0~VocK*n2bx5yBR-;6ohrf z9yq4&xNaQNNa_75JI*OPEUeJK2d4-NoJmT*w&Rh%Ugw#1Ej&VBYFI{M&m6DGru+FW z*uLP*w{y?tq4ROcn$w?R*EfJ{L=xjmkCP;V^&p^;pAY`vfW}4uzi{L;mWs@?vs6Av zz-j1aIBjo(*eXLs;C+K!r$UXbhigUbo(~sTPnTcL8&H;Y76Nlg;DlsN@4}JF<)o$7 zVhX7Cq83v$RVf>s^;jyOf$wnmxXXQ#3!NR0Bp8F$Jq0u;$EQt!)4hZ~w}p?B-bGP^`Ek^)snh3`h8@!|SDjpe_7j=@t6YFXps%m(9sq##!m-)r6-9Z1cwXeYX=H`k> zUi+8?e)agUL z<`{M3&x1X=hl7s|YOeh}rkTKGcIq6EdGw1c>4kOjzBDNMH2-B!#qVu_&ssrK!!xft zucO)=kF^E_j3-KE6}`x`&Hb1=Zs)xXJMfTc@8BI4^Q_%JHSvCFv#nM6^jA1YQjMS6SY1W^;zOLR{U%gX`Ljytwh@KD9l z&5{>MK@Tt{;VDW37X9P(8+4$MfTPXZKs<7Ok#b>;h4$gP2%I8>kU>#UHj==P+lVQg z#E03px(fMf{JEBg0slnO^j--_P}}*qE&p#ZiyX|?@^@QIV1*E~Qjp5N3)?)sO387p z>>)_eW^?;2=F3@52A(tlaU$EPBLz5B-n$-y=6(@0ZG4D&WyjrH`8eqK)dEt$JitJ= z*8V|CQ9M#>Q5gK}H2+B3C(jrfgUuc?#GR7GGGtNj2=rg%+gk3NUsI?QARre1kp#5M z+yF%V-j@pZ=!&bvo`K!SHwBf2NCKcMuVt|42@&zn3QlJB@Qrw6@?!U^JfG(Q>|A0% z^t8|p%eaq^V1Dh(P>}WKExQVc6lF%GVRPA+D)%xsJa%TF-Jt5|u__!cvH?0Y=Y=e` z-AQ@r$@1C_2MB{KkSC;otGI0M!Alh#!n=6PzW{1rOM%@Kee>9Sd_fw96d(kq3Ft5X zm?jAwym#rk+y$VL)X+5yLcYvy^Bvv0M-G4Qml%^9 zaI%>V|$cv+))^RIP)LN59ctB!Ety`+f3gIrMd zqwxWro5r7V!nMGAHc#h1f%W;yc zN4F#uFe_g#<+HV6KRslOs%c5_=1i}YbSu;sJgv;CT(I&`n<#dahM_)1A~Uwby9&&w z4$GHXry~XGw%1mMQ^xIBA*(=tB;XYvnD9b;M|Se`MP~07n=DILlztW#hn{4+&#s?S zrz{vDnZ#SV+}7>fC4ASY$+9|aKS%*Z&{_2s`4+{N?~Jv;S-ck`AQp>V^v>FjC^)Z) z8~k%{{lnnlfq;@?3h;EHmvYD3ml+3UL(C%@ai#ce8Tz8Ni@U^&B=0I`u=wZT}hC zQ$cv@`y!|LWv%a&{CF!qOk53gXWrvhxBCw%42`wG4(=R)TWqgw<7QFj5qD23ac zIL!ZQfkdxG9c5E_Q9>0E1xiDlt(4#$z+}w{lE1y!>gg*?}vynhbMJe%kM_71>242Cb^G74obNMt%jFbf3-AG5x~( zD7UM)n|t8i$y>5LR=sLmeDHeD$X00dcq}~2ZJF8p7J00h1bMu>n$_3g?(AE6g-l9@ zV@w+gQ^k*nt490@k}9mS0K~bJ`b){9;pOg_bIqWg?PWZ%_#>W}cER#^^$qEaxS?LH zF3Gl;`>)|9!$Ri_1Yt@NOkv@%5#eit@@s*-5 zC4VL|6iNyGff(Mq=k9m13Z(y*8mcIu3sqwf)LgR=8p+pv67#uVBxB6hkB}JXvAFDp zaqa`*`DDJ4WJ3W{eKx#0i;7D#C6C3re>qbXdgw1ZuR1BedH3SY*V&YShBZvi$Nd7c zij}J~8X{;l&+13kQn`&%E3ORMMg9#{11&Jb*xB>R*m5Kgr;U4Mu23ldJD(yFO8Y4{ zcZJz4e8HIyIA~ATr*1v7a1l(l$-`zh$QYCTQQP)}7ujDEPuXYW+8bOXnpDUh&l3)AcqLs%9_DowMQ*gIP2VQW{PyF(7;TN`XU$vM=oCa#3|+4Yq#q zT#&>)XO9QRd+DJL^zN_E+d7jpj;h^Nc(?mhEKcykC@PfzfW5&+9r_THNf?r(AttSs zOb=BwAA&kdvoVR?jG2^2XP1dM_Prh}VMh~eyVnc-bSOeBF36m;!7*AP$VFd&C9sK9mfj}L~{Mik71|jYv*a28? z`R!T_Av*Jodk{`K9nQu%JO3|&@mze8pr1d$a^Z37Ss3jHY6SU~MNhxBT<5^&s8gJ< z<7kOUmR=&I4iy3^?$0u64k-UPUPxwz?0o1bU>>y?oPMfk?{^irl#i*v=9S|w-@2V~ zH;4JYKu`ysQG(sSGx(~oKqAnZ%j{dP-oNd^mH)bGfA$yyO+8WFuz#u}4Wo{rCa7`W zJo97e?_E*3LqhyOKhLl87p|Pc4R)rP)gX}rmBs|m_aU1%329>2TY|>qSl)dDyQ>6J z5`j+>x5vZO_6`Mjfa`RW)wcR=2JU>@T{^=0Q=UKkPX$3#-rDlK z#L=hIhr~cKSK&hn!n@FDP=|3*zxjGF*ey;(3?%@W2l#xLiF{?1(j^TG(&|&zTWXR) zGH@gpZ1xr^zPcsy5a!;xqo9P>^1vZu$=eif_CsL3*^}dxCh*-_c!Uy&v3aRlDDu+3 z(rEHaW>D~vUcwqBb?ACaVB9^#Wb2Zr57IPNSUKNbsz(#+dCx7ux4MBw!{cFWQE+~? zsM(L;_jBm%{wRIAjJtn&M_(H7Gw)qX&k|g~d&CVqhB?1`+W)Bri6joO2QWt@Qf?|Z zJ1uuJ{#>I{c_}Lh)U2-LIUjps;0^tR-88NgN>64te%4G4e&N4#6zCzCN&b{?Fulor zDGSE3*%q|l*HW?F?n1Sz^?aXMXCP)$Tm-8B+*V0*vkq};N){9@2y>;PiFGu=aFYrw z5&BQjau^dU>u7b{$Rs$6PGeq_ytGAwEsctg#BiD2Ud=Vli%|6fI~zLod6oNZB>(Av zFAv`DkZ^S6kyaI9l$DeuEq0T>F@7INaTpq|5}v_*^M)NxJ;%MeF*9PUvy>0XyuDL< zlNv1TzUq90QH0LcI&FgO`dT(~#m5-gWo#6q`mOGd%_Q26=8_6opxNNd% zxz2SZ#DrH9)ZXyc=%}@kgD33+6S3JB**Q7UZvlk3miG<-0H)I`fg@skctt*rwtZFw z#SIU&Wslc}tX}{qz#l3}4pzvTT%U9D2h$ToaWvdry!W>4pp=~ZM7`73j0GJ+$&;vK zL(8rXb3V;Be!${>9)giIPOvfz)bgd0!ItF% z$%w0x`*ytI zWNV{Zci_eDzXT6@jOirHEGHL!+$sM9JsFtdhP?aSlODZzJCHRAxANX-Hw<*F)h_pp zYE}3^yc+T16&FPJ{yljh-01%qZc_D+zm5JY+(Zd@RNkL5Ouw&Ncf8XhZv7sR#R zsdh0{;?-q<`&Xclsr6~4!V`6ofgNB6paOkW6Dp+CoprR$01|{*w3Awui@DP^*%r28 z%^hJb9787VjA91@DF+jGM zhur%G`-`0ffsp!00WPyZm?~g2DMDXAxtD|luH_&30GBF^yxrnDx8z%MiJ-}sLlQ@Z z#pYeO#dlelyd?-w9LJ4gLAx?Aa@$BzMqWl?IwC;SdjWz3;4(HIYuFxBFI^_&J6sL_ zL2#&Z!?&7pl+f=9@k!aYQ;>^qP%aNN#%VV$(PIZXz#kbF zKS+E02uAKaRW=W|FP)UV5Sd+eB?m3r0+l+}f#=#vdE4lGFEh*0or0W=`<`#~4@Z8W zwo+J_RK}R7#O!yrZxF3tclt;Ipfz?@1pt*|ZB~^jP}K~^j$6L&Ih0$V&|6T?D0H

fTL-&$z}>rA>`=P$GJjx&P`kv69zKxl-^X4AC%XS1(%w3*s;=uA zRzSK#K)R7e6p%(rqy+?NX_b%;2?^;?kPxL6kPrz$Bo5u(a)2WxNJ!U#!}-<$^zyo& z=YGHM_kRDwK5Os2_FQw0ImVc6S@cn#FM{_%hk+@(NS3PSxPLq<-WRhsQSY=>GdFRY z!pZ)xq}Pdp3ZvFJc6y~2{(5Mh^3LM)(`5aLZE<&`ZqTvMc3o5R*6W}aIAve7?^wen z$pBk(3Ah;5vfyiEzyFQ8=$+hp#^njj4yCOGpPbm21A_e}Puh|(K^F2A8^7h3)m%$w zZXeiFX`Fr4ITcXUxvs{0%nZ`)pYxzZx9yZkRX8mbIpbqb*SqlgvvxW*3QQh%1!Ri(+6QDt191_;Cf$&I*CV) z^60VtRMY>eLK#sp^&-fXM8fc*E-IbyR7maZ+8diKHL?Wo(GOyT^cAb0SREMZV*Dup0#E6~u1yqZ8At|+33Hs>E^s?3zpCqp&MNKQ4eHC`BEVzQ>ht3pOM zlGgF;cb%NE-8#W2(Eo$($u4&R?=7=0T2>IdBib{m`x53IGg?M<(LoJ(6ZBo+{RmS! zuV>PRna#~GLhR-MFL9l6wQ>e^v!$*A$;gWVFJn(FNC1yiEY$)y!esQcbv%j$mAcM1 zey9|nNTRZ;ud=KH4tE=wzNmFVBsTIRUO+$s+fde1xm(QS(KPW!x8qd*! zyo3YEs7Mth#$P??(k0V2`+_g<@OKZ&;k)?%4v%!O2>4B2*S0f$lB&NutXZ;=35%%O zr{zlAJC2$1A7PY+)$9wD`1}YrpTb)Vo9bFOi!C98*AF#&?zjmITU} zaZWSP+R&Xne>8A=n!zBocPyoe8UBjOacfiU=iBcU1}wILr;M^EAFY% zwX<8gSuaNVlRHi#(#^Nu;*DD@jvw|;5yZ9?r_RcjS4E@pYoPGhDY#nF`6yDCoa!8D zQRPX$dAqx|l3plvo~5UAFlzTVM04Np*8w@e-u`S^nQxl4T8OK8Ls`8li}5WUVc@tR zPw$4Kzwx>8e4k$O4$o6p&DjGraH`nH;-reeyQAYyv=RipOkn;;pS7y1TEqv_&jvBUO0(<}1zTxGlyl)-Wq}Rndat?)N)L znLtb`Laz~k64N!MA){c>g`Kw9{gawy*ARqqUBdeo52jd{5@|C=@dvl}5q>w=?wta# z0}tHQa``v2UdyDAyn8MCi?)FK`csv%FT)%uZAPbuq(Bg`Y&eJ3eq4}CwHhkE^QO>i zr_x-dvq&He%luX{II^DrUo3DR;CYX(!gG_tO|_@m}Fi`=7~LN~zmI>BMG9KvqN=ivuF2F6w3G=hu&KOsqQ^oUXCCmupu46|=M*2+v)ktx% zAH-FjT`x;YqDPF4Ds>_!Cerl!kdlz!!c`&Vfe(FH@w^8R77J5%_5S2~f29U46pOuZ0^eH0iog*|MU^5mRbAo;x?$jV%!hSmdLaVwvVZ zn+|N{9^EMfnc=9Uw2__H50BNuAxtU1J*v%LLb(*vb-<^Cekukehd}5mHCq~Sx9FzXUWQ4SgnD}AYaqF6*oT?W|j*B{LT?a2dXP+bwSAj&EZuZ&QFSv1ZZ`VR(}`)*W9jOs8cwmmA3eshF6eU<%o8Hq8UgqXOB9u z@vC~J6}iY-qaJ)$K%YbFB6DHUK~O$feW*zbR3Evlgy4`q$Nw-||ABerOgYk@u0Qzq z@?3$iaph{2xH4Opi8(E+xA(18ju$`mRafv&-MAL-fZ&4g33MZLbj{k~TjoNI+rAhs$6B@U_PKrYeDhqnwN~j~PS9)h z#X@UJ`-&T-4!U&}eiYY+ex^bmFytboo0A9L3EoOQy11&q6+Y3s!au$nT(M58iGm*f z1;#&mmg#1s^bp-`zD{OC%xZZ_GC*LK6*{9d>lI|0z)>O(1799Zj46jXe3TcP;f$&J(Vd0A43s_!aC4cvNRCE zHH>rnZ+T^p~1Mz+PA*(@X1Ce zjq;ZiG$O1^zKVgEsR9jBGVJeXx}V?CX=<)<)TGTPC-Se4{%7PekY#Yy=47|qv0 zYm#F?Z#1;nMQTIL0DpVnFikRuB#LGg{!Fv^i<}_mSKs^lH$jU0PlyAnHZ_&a7u&wg zsfnf5$4I4@RMYJET|ue!qnOsUWO6EhV*U>{xXCe6Jd5@#MA%xSX-SPH+ACT*5|&x3 z30+rKhaI2KKCc)ERyFyGOqq}|)7;94(LnkWhknV!{b=%Nf!WEtm623n6V{`VHa2|A z40!8&U#8rhc{qBtVQE;{%?^>}6e8|XxY=v(mihgCgKlmR; zUYDQP0x0C)JO>am{~)ryh_Dn@=UPj3V+vfdc}9{QSjs#{*W?Hb*E&b1-=IC=W#ql+=v9SN4Ec8f%mCo}EG-|c zJQz_wL`=p&K?V?w{3ShYbKNt%rAoS-ve&G=+0@u`KwiOI@os`(;?1xZwjsmG%00@J z0E*%Mqbw`U^oEw%XkZfv43qpa9GfG+S1O^irWpraiP^QEZ5{fI^c~=2-c0WI%1&3h z|AJ~@4qN6Ws(cI6{C0NmKzqq}VA4lk{-##k9hA4u z%5NGND|o*s7AA|mSiAnFx8{hD#I$x_W;LJWERSdj?xist>JudFHv4j3H=iZjyF22jN!v{mz=Doq_-(t$b`*lvl zW7CKu0|;kdVxZEnv(yfxuV<;r;a{oAKTYCPb+n)Z>nS-CG%wA$;=7R3X4z&uX`AD0 z+nh|ZT=ts%KUtWT8L^>BwM_4^)1od}X59;GkC9Evzay$0sN(fLd?>SL=mlZmZ*5#uMBQd)FRLA&g0U&G@^-xj<;DOJ{p(aM(HXHBNB zX`eT(LwD!MhX9&+)%I)BudDB|#(>W))gi8wcb~{u!@UIGG{{pENfV!q`SoUTNu}`j zL$PEqhouLxA_NIC*Kg39epHw0w^yNow#Q7@S8EUWJ_CcOlR%mPYqd(rc7d6uNmL0aP#z2zApWqD9y3yVzvM!FQDfA2d zHz&tE=#2Ww!q{80i-R)h;}3}tdfCwSeHxBPB2zKhG-=@qWEa7zAGw;wd^p%E!TMT; z$4d)jL5Zg53TtMA#u^eEptJ^)HhO?Xvec=x!V@?7j`{==+xKIh5F+ zux%Zel=?E19i7uVW$ibI*!o1PHL_8YFU~EWu%9$_u;w6s+dOT8nS$J&El2!>KZ*RvJSVpL6$}OMJh{d!6WiBQpJK zSx$W^SV4d2dpb4l{51Ucq%lKgyWL6_-0oj#m}NO?*mLy(@q|`CPV8s^oL@x~zVD4=%9TGx2mB zams#Jm-F4TaWrKp7nrsq#fP49TeFU{zJ8O~AIzu_qe1n3hK&LJk0P(?)*X zzSH(bx*|4y>2!;W6{+|NA&{Klq*P^iXTk-6DCP))tWn^QN@Xapd5g!Durjqk2Xu?;ppa75Lxz`&$7X3B*= z*-%xyk>Q;I7qH=b^&Xh1!y*yllx1`#SI#j!3Zf~bYGu|cbb#h9W8DG;m1VV_8ZmfM zH;w_aCSox4!-KChrAqV1TQdxV^u8)4_#H1qT#3l?w-5B2e?XnbXmZq&2WpN`fg zAq%^laX&<3F`a*qK5H$qp7F?f>`@6a(rs()ZfEg2%;V^*1lICET7Fvu+^Cj!u8us2TyfwjG=;W+a469v_)TrH4Uw_-@&1-3TDa2vD*pN-S zb$>vGBY2T&-E?uTA9@*OKrfy!1ogRhvlhRTLOW*S;%=2NpmW3H%#snvwqgPs-vybQ z)y@^Wt2(iNLi1I$rj`iWyvVJB2&tDq*%4&A7orb5_nn0R{0UtAF(LS;tli8}zmdZm zpU>t4i1jBtz5~b#hn@)UZ}gqlyUp~eK8Ahy`@dERN}Pp&L!D_fJ>cs!>)oR z`@ZUHcE0K@Ou_kbq2`Tkz6TH)f-|MlaXwAUeA>f%(VaQn5d`Ux;yFc>EDraX-2F>T zS9joD8XiZ-$M3%JJd*5up9I|*F!^VL98bj-ovKt0EwxdD2YUFF>?65<4=5X?g}Occ@BSMY=x}h<;}OB+Uwenv zYm0Xlrs1t~3{~!HR_E-e-U_-&3ld!+dyga8<9VtkCc4$v!{Y&;%4E^f&#gOG3Q;eNw} z9B_TBIOSPgRP$C_8}zsrCY|b&FFOCOdK`o5RaZmMI;p?df=?sJ^T9cWGIU9-INm=>zib*m``y-l1#W3PZ$1x}fRY#R>dfNsH&3Ok2vlE$ zl-{pa@U$0t1mz27M!`67IoMGmKXxO?H0ap;oCde;O7Y;K$h8ry5xkMuhel0Dzn*^O zHT$6d^+$DcM%tynf6UO2pw2bi^YORd3@n#2O4tOC`WM^qtz zXai=pfD`o+rmQ3PY#h)&EUlU3H+=B_saw7{`9(s|tooT{*Pl5HoK5`RD|EXysZrCz za^b(P2X|Yhh%A~A1`y;i^CMn?B_IOfGT;M=Rq%3wP3I2C_I@STnbbuj(tNU)EnWCC z2IAEWWo=_(oyAM5ouZ4oTn4P&D5L&}os}vPDKhC}v%^Q$f0&OTl?3w}mc%KInDO#) zd^s#ubw!@L-F83W<(@xUsJaNf%xZ|5nW2|%Z7QOPFN#>$SjSRl0EnIdH4}Y*#irMN ze4J6_q8m+=o3du8L-|xO|7%C=B}Ik-ZDrJ*yfUpsdSx8Mn#K}S_Raza;@#3O2zsLI z)v{t~CQPJPa2v*EUWEja{f9Q=bUCx}3lJZ0uj+JS_zVLD)JWljtEgzTa0H_WP1_Ce z%-(l-ec^&x+xBeV9eI2&6Ta%F*a+X?FFqBft;i!Ir^>piphY;;_4}A!QB1|f`T(Lz zKk5~jD&fs-g3bBI>0R^12@-Ch2MHcAh~?Rl23TL@OOAAI%-2T8HA{k(yI&6HS&p}N z7_DhK=w_{bX&jM3^IpEeREMuBd`c>hGgz973BLv*QuQc{)!__-gQndz6vu-Fp zx!$fFaoI>=GZR@2@<{4X=*j@TqIn1lXTct2QEZ=g2H})#wW)Y^tV@}D=lJwSz5ts& zTz9rkGo3n$V7Ae8$V*tWS4P77P{wPTppHXd`f(t5-bCa`r^AqDcNU_%i+PZux)|#l zwuj%JcCSfT*YaRumC>IRwqS1})oJ-Kht_SoY=!6CKlezoFhg#on_Q-RR7PL7j{g3M z^0BpgzELcLAL;d3^$_ZRBqidW8)m`*mqtQ>xd9V3?;PeM%Cm1|>q!1qlZM1Fuf}|Q z&GS3#Ec6paI&oEG&HnjrSLD3QuU*WO6Pfr$xodM@aYc7$=oh zu~L;&hx4R&zm7sm$dfVC=d{bveI0Oz7?4-MfT**E8l%A0fGfnvckoh(x6muU$l(;w=m`tQ z`CNz&=fV8X6&xUm9L3`r8A)kzYAmNI>C*(NLgmp?lh7B?N9??wlhbX&_67a=$S~0{ z`|%aaRi{nfAICu`yR-6;@$J|dTLVarus4QV_=>p|MW;sPpZ(ft(6ZCc=;&2&axy9x z$p9wDH(Lz-X~@07@4{ScGHAfL3O7vM|LNK8A8xbymbhl`t5)O()!H!%l8UV7olA3L z%w$#wsGwsz`cZWEq%eH%dqwkh6Zg?Nhg2r7&}gWid!1xN#X}WI_eao9l#~xRo}g&u zk}9_e(}yEL~jJPKosW{1jadyafaf8_1(B(JBhCfkC?9g|V5Y=^Tf?!tTE zEeV?B3(N7ORC4MJRFhZUOCPHVFnnvm$HY5!X6fQjdD&A682-pTPX7D3^2Sm%YC<^E zURUt{%f~$Cy$E4PCI0?t?bT`u_+uNQ*Nl8(YzNZT0)=2&kmcbeVAQ(brE##(G!BU& zbwO6Jh%E-%FqW_R%yvi|TDd&cIZ%trunRU#d;x3F>h+WySXzOR z1OGtBzc*E!5EU!qEhmy5ea`e-Bw4|jLUJVNLR7vvYkqE|RKu_j?}~1q$xVHfcZ^P1 zfM|76(#US9BaL5L|7C$U@?}WTO3e)bwg*@>t7(#Ru@|wrz$l`V3MNN^sHD~*Y`MKQ{t7~`@ z1VAv7>dBS^HF8~Nc53Y@)}h~uKW2kCrq$h&xZ&|e zzjm{&S@7V2G?A1>{;LDj|2mArKMUENy{GWU{0P_v( z(6l_3zAPOqiT?DokE^d}VI_bDQ*Um`*7!t({XXeJg1>>WJAl6827=LV*R@h0@BnQP zKEL(HPNTfV5x{(>iyc=jAZESLzlJNeQk!(VHTj7XqaCSrGq~x9rN=erXVd@KB!hYZ zvU-$PFMf{;%DELj1#t0ip2YUi$`c7c)NzDnDX=#0#EF=IKuTStcbb}kUGtlJD#P}( zpgzNpD#edtBsgY&_ULliCga2vGBF1}`c%|U6V4{EI{vReJ$~>UShxM$Q84S5OIE8z zR+BBN={HLSPy9&kcXAQzxO0Jozqu<>ViWZZY|up=pFPaqdJlw`|Xo5Hlw)W{i{U+zJ7T0HZ{2F>JSjC#b+rM)C zXDT9087MLS`Zrf^HC_xwKX9W8M?hXO0a!z)Trdi%tsoO3VDbB`LZDOp#L&9%mg@EH zWa5W7jI+-@t7b`o4;%|2%4x8Po^=ZdU-S)hFSQ~)z85z?ONUXNAo`?FQ{bDj$7L1K zebKWV4REC2cS{RnQa=bSgcOUmYdss%4m4E-)jJP(_;76TD0d4fvui~e*-5Nb!^$y; zH*eJ#IfYXWD5JJ-Tm>^(eQ5d=vxBc|5!F#Wbc=f-d;MdZ-bhCu#QP-Xt$=CN%6%qp zlL_`|qdk_VQB$h(KSekoUv!Pe%I?B%NsUN`{C<^pI7o5sSRUMByt9RX5Ck|i;{;H( zD^k+`@Vkj3+k0KYBuH^PGI%mzB(dh}^pO&)nYA$r=VjsrW|OcaZoWki zHDSjH81in5iXd=iwwRK&5ZXHg{>X1PM9^Df$&mR;)K5@u&9zYzu~kNb3bd~(9ML1t z%}JGFQ44pE(GzcHC|><4y+CD=I-7iTLMqVPYV5VE?PH5judePrvQ^WyG22ir@zKsZ zgA1IvKT z`s9fl;cwsCTpq4S0D%^zELytEdi^*+CEe>qrRIl=YSjsMoL3KLA)!IW%^ETNofxda z%3LFqR29V^-hVLrNEW>j|I!ofLA5&Ys=JkSqVB*E&nbCzHtsFs2f_F)|6RXD(>@;| zF3KmpuS4OxRxeexX^G=Sy-}OxlS|En?1|_7;o4wQ54L+ZEUN`3-d08x_^0ZlN^=#a))( zG^@y#XH|U?1*~1LX?cnZvhwhcxjW=Ws?S+s3`ZB5k2b< zkD_rNd{*BNIw2hGDus*vs6?}yQ_y5cvO*oBUSvPIewlJ9PC=MwY_yq}Wb|etNvX<< zg=&4BAtO3E_*I_c7f>}iE^rgS>>tvoacogW!5**?hJ)v#$nuPPj$d5%*d=#Sgy)j_ z>tRE)1OK*<-Z|{`2G_FJI3_$a)z?^DOi8>;gOU%%*`KA(jSz0N706A6CWqICS{b*N z97|4Aj(t2yxUVF1rKI9RbNC7JnY=jur+=Q}f^zb@_cFSm`CZ4xHg-9^nV zaW%+g8|q$@8F1fxCocYQt8zD0 zuf>t(IUItUYnG(h9Bg#)KRxgMT5khwPs^P(7uF%5^0G%8ziG0@=wBl??0eh8THvm~ z#;>QzqPIUYeSTYO#Wl`guPqed)PYbz&8Hzf`TYDP+2wb2jiUfbpZ?gqR?XYLxfsrL z?xLA(HY-FWzrp?iMAoTmR@1l(5VLWByT>u>=+UEbFv`BP zTRH|rA182Zyd^(cr%Z<*r_GS)`ol_gI zF@hn;B`D4Ey+Y0QWFa<+%oHK2ijMNb#4B!iAtkk{t~+bph=cIEuk4^~R=# zLs9aR#EjvajN*J#X)6k_(vNQf`G*#xnR?6sCln>7MQs53_PyZXlZkKWy_8saZoY3D z!mO2gIo zUNf&&~hLfXhl!} z>LF7@&{mo0SG+6;6#3w@0^+AA)e~iz zQU{^=ti_uP>~j>X**KeXvf;NF9ggJ_nO^GT7R~i{(R3K`Y(^ikE9igeWf=**9)KInn_)~=u+}+)!>!u0VD|;Ro67E zYTrpE$}cG^1s+h$9yE2;-NxRx0t!vWQn5t+toS(EAF+DksKAZ5e_H(C>@k}(K7JG1 zNZkZv^v0GLYm*_(6i0y>qE9wUGHC>(jD0e;ud^wZcxtMS+)Skyl1FOedzpuY)_`fI z7g5An)c~!@$B&=^|12t?p6W5{V(`oHqbF!h#28-v{@k0@^M@#($k8RoGF#hA*{DJvOuu0^>)nY0>|{+4;rVNK1~zCnfA!B>8mF z4&D;Xn)zwyh_KCf=eflB(*gX9QgC3>kb`6+hMug^*vu1|g!46V7z}%@cuP}qALpJK zC*&BZr2ORvo;{@s>5z>$SVQV~Yh=cGRr|y zY{m^myQIiy%Xx^c5M3d`?%I9r;vnpMWp+Ww9o5%{7hQHHX?U_PfN` zOz$CcJDJ>R-A06>f}jTsh;R~~h5&h!01|eM>jxf&X147|Uv_<$IzlRs_h-;E*$tR) zL&2=7OW?Z#N&Nlkv0?XOzCeuoj^bC%Wh=DhJexl@V)<)VuO;@M?T`biyZ$q~SkqOD z435MqfQR1*L3~M_4Ucpo4eVu^46P_sng0`o(O<<}6|kii(R}0T_^gQX{7o@K>Nhln zuqT6HZ|nQxkH?)UOZOTOId$q}RD%AmE$~3vEagny7|m`+%L*T;P&l< zKDPIt#TD*BR|$2Wwi`A^1VtU}mZ7vi%BN*V29PuE5J-NLJw56yYYteAjGuodqsp&g zA}%GxWNCN-hKIjg0;=ySkc`0qO)+}rypF1}EgMw;tT1wBzXyfrC zU#1y^sbj2nbtaM~{0Xa+&eJh@hfj5e;m#wb+BADK5A*bMu<^@$L}tUrhPO@&5K!@$ z2F!3gD2Xv5%z0Gxk~O5CF~1YD%N+gIp1T4exp%3y4_Yz{VFQIfA7S{#F24y4|#=W_Dx zyCWzaEj@Jvf zb%IS-@0lVAHBB$Y?rHhv^9amCB}s#Lio|t}Pr5y~XhTWu=OWT-A{2<0Mm5az+Zu?; zAG~HHy#9&Z!dL=C*3Hd)4&4~NTdz9j^&BH*X?Qb@ucA&w6*GwwINxR^4xT=8qVX{P za%2a;y~Uh`Tx=!pS`gI3u$|`go6|#8CYX0bmxL~VP1fuhDJ5%`egpW!KASMB`@VFQ zux0Is0W-WBtfE}u>a0Uo!VB`Lk5*VtH^dTEsJ!aV0UW7!tLlwjsy$i#?A!xs9(fyzLf~WAW^)-i1GpDGBKK_qQu`&1ybvaBq%57fYptQ@7c9NcW{H zUq?sc5rG==SL9K2j$E5sTVD%m*5Dq><2~xy?evFXuvzl(urOPiZQ-lC9;skrOg^JP z9L}e@NstVh?O3LeP@M?jv=(V8R)Ihc743)R*Lrsq)qQ)RKPCb)*x5NaWfjt@V2I`!AtrcXNFprDZBqZdB)cSmCs=**xBc+jhV z0A=65@0QOmAQ8waws#!-QeQhR-bXtElI}@|xuopH&>x>VOD3}~+RQ}q(jCl!Rn*M` z4DbMw$BqvdpP)Xy-$l@ZS~7pN|Eaa`=oq{6sI&=%V+}&?0b0bFTaGPRV}d!ltZ%!^A^{%Fh*!b(gPC*o=t_D$I%%EG)x{9 zaR~4D-}i8eJ6emW=M-iai*ds4ESOs)Z4!_&R>j>-w$ws>@IZc&#@|pTeOx9#b_tn?mqbK`y+>Yi^O5{mQ>E7_EwWO^Kb!%TCa4 zx7jT$*yTm?{R*A5IqA#G@r9?zm0btf{|Z8*uw?)Q*3|A99vUd} zQQL~SPP!h4Da#wEmYy!XluhG*1rbr!GJ})>vJwI-L9PB~oxw34jbx970t1Iv>ZXA6w>EDDM%{9cH)lMI@;0mb zQeorO#`-B*aAsDk0a^;Vl)n?hS|%!n|Kown-W zr)aPWCKGwB&E=gG1ME{kG-400_`~OO=dr7I&4}^t`Le-WT~3-WfdRdVz&*TpH}1K& zuW#~k?b6H7r?Y$y$u5VL5b-9oy=TZ(A-xS9luDtGziwm>ZZJ$wYcsGu>>SAtuK_r3 zB4&V=X~bnPN@&0Caxu?0wqM@Ml1`hFkYG~m(ZLHA}CCuRCB`#(?FX{e%`lvyJtW%^YgT{Ha3eoRLl0Xc3+JE@h8s4KI z*g#MR{I+W{b$GS#{{%yt{q*OBhJ=7V+KH$g#&4=~T> zHM^cQ&45)g$cn8FM}FS;e72*=*C${_MSC@9!aW4;dB6$h z%vuZGuSzS?^uN8Ne?OuB|8EDgF6hCz_tx3VbUN+npLIG=!Rd6JnxOPR^_zd+ z49u9l=8)lju_FNU`#_ux`%Rdc_3V7H)r|9Dxj&A{*TVs zM3s{J;}3f?9K=*!pa(&|HWnRghi~A7^{3m4BD%jA>Lo_H4+`0l;^lWh2>kBgOCkyZ zONWp~N{>f>pt6DC-)pIcyqGe`w}(>yiN-(2UfqYbIM$R*fNu3!TN8ER1-)s;lRjmk zarw(S@yL~tu?4*;@=>O5?f!+t{5{A(y2Ah9|BT^nOH)!#R@~Zq{7`uI2gU5bH`Dg> zej(`GO^nD&gr2gt(J?~aP_PTI@2irbYaC*|X%BqlJl`P_c~#pc*zLBkUn}P3e(1Cf zmYw0>1SqQmH$>2Sqkgm_Wu;Ml!F!I36*=NL_hIw8=SFV7^;Pj&9fv2m60B!3b2+XyjS?nfSL3fP2|+f{_T?iQo;ST z)Kb*ilN$h=4e+bK4OZ%*Xo*~D9eLO~M6QN9#d`d2-`}WV*vE7F{;;^?Y09pwB;Fa# zrnwWgMp`V?=%Y@8$Zi03i=g?_f3%|MVmu;ta@) zqGy%bT`g#S$pK@ARLlHfRU@Acx*l>(0KVq6JsA<3)GPFo0$#mLlTW0GCijifbd9n=n%I2x-F{2dH`B1iA60Cj zr>{);M=|+qp;Om_3bv}t9rAzp-YaN9Q78&6pY*b#X$-yJG@CiFr_E5&^tsxbWa=9a zMg^#4mtK`Cc73;Q8THkz>Y(SFON+Xr#EGj128Szlt*Uk>um8TqKh#-(I^SC$H=+(4 zeQ7GZ;0m1HJ4Yb2pLv1r`x*1KcmhS9KKqjo!mtl-V+>A`xSv`f-=ic z2p&Iq{o?dG?`o~Tedv+lA8Q1F^?Y0^(%jjD zVk!SaEvCi@d7jyHN~s3!ivP0jhxdTI_Kyp(;j8~6>-pS*EC1WgjQ?^q!05n7b>8x< z7oQP!p_Y-^1Em3k@B=HyumqI*{|Y}afBc?=ftH=}U%As~WNr-lt-b#P!TS7j{vK!^QyTg(PU5jfi1L ze-{bh?-!X?d&Qp*Dwt1FyGaMO8`u#j?sm(o?Co@TK;#bz4t8$@+Afh7Pf@y(zjl#x z>N3=-CIm%lWx3QE?J><1VtnJ?@eIRUbNy?gFqX7bW#X-dA8nAa&8E}-l! zy)r!;D-zk{%^s09;#fwPsceXqMhEjrc-*gt7Gxc==ZV%U+)Jy_g4Yp*%4xaax^4Pe z{xi<^<<=LECSWL|j$qULx^w2Xm)hE!+S=K9EtX~yepQ=z<9_Mm)&in@%6x{Q!7I~& zvBKe*eZ9mqQm__xPg;9=Pg{2z7!eF>piGFAN_rKkpmo^cP>5>cCb+CO9HazZn$&8TTeziBTXpP&%?t5|cZ=gWD=HY<^*r zTb62c*`C3Z-l$6c*mt@>mRua_pkdaZ(XiH)kTv^!z5x}aDG>QCg}t7BIjhCu)VtfR zmukXLk1?7Vab;_mya3LQVlKvs;o*P9RXP4S3^DtWHLHoxl>8v3GS}Zh)?A(L5KqVQ zWUiTmo>~2YqUF0?tMJ-OcCBy12okG1x@k1qI$+9dj%t)&BCdjQn?{oHZuUt`T~Yd z<4Z{C)!s1do~jWHvmIO-3EFXg!PScAwsbxuhY}?0%1@v3@=EU?zFu|rk^xF78b7O% z%4;D0C=45z_3vL^(k(xwOpoaG?L2%y$CdrmRlGJr7!O=qgx6b6Vx#w#bY7I&QYwcj z!TlD`OhQz-jk2$u9Xpt=Yz}_E9YoLWFbtbK_+jT>EddrkKmaza;UBg)i#IyM(-&%% zvNxzjxBZ-2)I>tu@(TGYl}LQoZ>Lk(5K=K>(mGXpR%HNgxiVfhc%|t*5AEc*KnOS-!2B_u}4ci`uyZ5@eX0wZTiVS zi#rC}CRr~X&pY{xmcP)`DK4-$yNNQL$tUvt9GD1;LZaxI-OL7epn>J;Sw`4i zDziY8eKuh&S;Gmo!!yQr^`f^XKN*Pgt?%2gVuV17wQa`Ph)u0(O7FE$cO**oY;dnh zY?8&b^M8DM$6#=8rt-nAVV=@cVAWARW~uEjghcGF3VV(33~$K4iTBMNZOgB_zFP2E zYEolaSDfCu{4wuMBEAz^_qMgn`Y?Hg>-X{m}r z-K({GN6QBWuBWFT096VF0#1XyG7p%0;h0aDkSf@4rEJJM2mbkyOO>E8#%F;_> zQ`!;N_FxPPUCD=03ti83;R6|W%NLlXT@w!e`nphGG+tCw%m!9IvgUz-GXuVrUTEA|9!cw`neFw@Q`Edr*OY5lRch_;J+_cZtlvnU*=@4%KH9s~y4C=j{whP+A06yfQgxYw;2ZXL&2?O4+H{Z;dOzE_f4;s9_S)LpO9XrY5)nDq(GQNH5ZVJ_y#<)<(B0?kY8aB--x%%sry|S@482 zD^lxXz^A*5rnjF+dB~YrMhgy}mSKPc>UKg1Y{n#i0u%4lkE2>gsXH@TSq`kXAEL=k zN07TuN7Z9v2~4D42_Am-5*SK;+OVNLhD8#D1u%4A@XH*sBKQ1;I32|`<;->*OA{23 zhY93Z`L%ax68#>o3BD|Rw;F^^miFD~%#sXP>wBMEDZlZJW5xH$aPiQW@0Iq;1=+$h z(Rh#U@8K(|*5~<|L`%!w-xdFf#xkDPw0%QrWrkm+y8eCk9&ewvnB&hc=p|$k`F`Y7 zt_vw@qLQab!3=Pg=FQbWYf|m3?HyaUa|_7C7K1*~?8mmj!*9s&*a(LWiLINZYcXFY zxGQ3t3X#$bMOPQVZcQp^P$RpM2|HPzARH#|x*k;jB$wLnXZXF~N083q=8*w?!{|K{ zHeM~#oW1AX<+)c&?yR@~tZ81)l|-5B0#80feXmEbu|#IKf&KxKev&z%9#*+pUF%}$ zKwSJOc7HUq@+;=iD?b`v$cf<{PGhfRcr@#Y7iDVbz(IDev3=BXR(<;wi}v3`4Ae|9 zLRRZPu#A%WK(sy58}zAG#^cdguJBwRzVN_=_wLcwXu*AKc&0AQzpLr<`d9%o=i`e>)q#)lN-8!MVR5`(s*OXyOwo4N zkRN^kiTmtC-SD+tfy~u$gxj4c`9MItxv9Cba*VhdFoTHM8KS8f76e67%%*B}XbqD< zN_sM>gWm_%I~t-{-1Wyaomsml!UIy~RLW$h_mFRTNs;R&M#vb4HmtDqIfkI1i~P8B zf#)Hj8Y#Yo{J>8(&}r*GB=t*rh^HW9E<8PGr#r;Q)A;0aYUsT9nvj&@vS4?l36N!e zJGW)eXN9 zTQ5-X3S9~jwta*qNAGd~p9DmXv&Y&3b)W@P9XodYpiz4lfdziCHeEnw4^^;l&Gg1Mkd#*GZloJTl#m7mB&9(* zN4i@W1(l(5=s0UYzwi5fdtZB>>m2`)Yvzshu6NB^&vUQmzV9|Eoa%czBk31inviC? zbPyJ~q4nw$&q|-Sq)|rS${R-RR{S-0OKfL>{MmPWH)ESOkB!e;RzFDy9-Z5{4>l?A z(e~=T_diXl=9fEId@I4p+~iee8;jG8-pJ5Nea#ovW+MH83yzpnGy-)kNG>YM2e1IW zJ#dkBc~|Neq#VwlXI02|UBrupySE><(R?g^D+iCY^JSiFNULw6E)D-Y)clyimgvPZ z48QNlI$ED8ptSe_AuNZB=b>7(Ow)H3#{hTyXf;}rf2KoB{?xF5>5Te&5OV|9IJ(rQ zk|uFNeW&fJFatm8!il3ZjX*TtWT($^N}S4s1xQsRt^PJ%m^^wE*zD$Tn%~JZ<`nt0bOq1%5Szzzk9a->ohz*8aUZdu?UNy9 zaA`y!$&?YqY46yJ4Y?KS&pT}P4pf01!B5~>Ah5}XQt}bq44}FA zx=lx{+{{CiM@l5-yeY%h7(2@Jl!9Xg=;S*)@l=2LI~T;#irrfdi5u&JYI7V z^BD^3B>N?Ly`7SnsM-2RHpTCp`BJTJ=~Z*ab-Z1w@DDc(JEr@RC#^}GewJA)-k~bL zfvI$Bh6EFxijS)927X1vUgvz^VosQ7e6N{F=Dih15rkky8d&epu<`!Mo(2>W%~8By zpNQ6sT+bik?ZB;7vSoD7&pEjb-aWMx4m1ISQDnpWk~CrTk}md0|;&WFju%SEl9a^((~4 zavRPf$*b+uCM_v?0 z|9rM(QDV5@Q=k;Nno9437^E^rSfrOhV;Q(DDW>E1TGr~6H1su6KS96W;s%h&r6%on zv|uI6vgWm$Lu)s6OdF&%I;JQIo(bJ~ohjiy+M~;~Hkys3P z`kkicOH2DDcY&&shw)Y4_Z~gUQ_HjIH33oRKWBwIx<+5U3QuIu&p%H&)OJeI`!4y; zpKG;sNcDQ88eZS-zCRUx^5CQ}1g78{t7Y`fB?|5m#a<@jdq?wOT5}=;2Gx9J+sMYx z1nBg#Vf&``jgE$Sy9PaD!;Xw;qpeaq;qeMLmSysYA6qnY3ndgj9^2%cRQoS@zP&1) zf8dfdJyFt;Q9E=LdP}@>&%1?_Ovib(O06S!Hd?f})}&)#mp5#Z1j2Xuc=3*?3&mzT z9q9%>k*86tGUWtL1##|ofv#Tn_|splfy=*&&2WvOs24rlDX8?i+_&ZY4aIeV z9_SMOHV)p`tXDn}{%Rl4Fc>64PNtP#_6AO?dt{k*XD@Pv_SE4fB0NOt>)4PK&LY(HG3mY)8F8*B&Z7)LM4C zATc2YZtWB4zB2_xlS&Mo3B(#_Tev+mAADPS8pLPLACbt- z_eI6m`DQvp4ecKXoNbPrzLz{r{u&KsRC`23{-$2zfecR!lQxTDf=cwmyQh;3-A>q~ zGxH`-9Sg;mw(=d>BX3XBli-yGzS|tgZ8L$E*wVB+=<&Kdt+mgwT%vF(z4y_iz?r4= zdlkJD;hyphYiS&O(sUyU^mdhw)^<4~ywp3IdJX10b?2WYZT*K0pT5}3t%#nJ?6B5_ zhdPZXmBG;uAQreX%(4dQfYl+zY~_TuuEhqLenZM!q}d*JtSUX%_5Hu?dBvi z*Z*8t9;v$N>eibCRh*Yu6P#8zG|4f3D%~T@hu+DSEEp;wj=-wh5aDqfciMtalYX~P zI%V-*^f!>}vDRfe+x$U4KgMz9%Dd~KQeX=-xC?g1o#EsyArIlf06Pw((^t>^e5g}*i;+^2#1;#td_aNGL zyQ>YzEE*n_VAcuu>uv_FZlR0kAe{jhBC+{&ww$WIo0uR#I=^)j|Qs3`2$}eIC^SMLg4CBgWxf z*M~H_x({~I%) zx{ZmDoo$79zfNKfF_w-|*gfBMSvWT=9$C<|D_k|sJpS1j9i!?c8ZL8N26H_j`!J?>J~SdE=b z;tKYjy=fd&r5ReNa;9Cktrtfud=dH8XjiJG#Uy@5hno1Z3LoDc5*5Fx3*-T9JU<*5 z9vxlhyP4UnVfI|M8eQI)U?}VwbJq_EB^Q6*UodL^L7KU2{BQQ~eG{t2>Qg%gQ}8jz zgXiu{!x(O^ z7x??{oZaO!zR_-{0qIE8XMeCf`CR{rRqxt~!0WT>V3jYL{gvX#U*(@SE2zm7_G03* zckL4#wzlf;xhv2dsCtazU~#K;&8b_DLnz)+_rX(5#vrKKUTz3NW%(HLSrgdKCLVX+ z+29~lP^r`X^USE(-1B^dRea<_UjyMILoQ20V{&p3`2(grmT6G za+2R&A~YX`zD{n+z&yv?>t9!YIKNK4dn#}B692W_QgZeAy;r7xz4v0=NNxY@K}>1- zC2UZXHwuZ6Pib(d+H#QU$l27Mqa`UxO zlT|~o(o?Na2ejauvI|!$RNx3TT}GZx(n33(QJoP zESa=fXD3BgpxsuRMk$FKJ1hXa4sO$wzM9VXW5t-cPEBIU@Jxf~DOV^#X^7N~qapN$4zTZ=TlIi1{VVDw=BJeJ>q zU$eh+Nv8)pV+%jRh(f=Ksa<2^q@#6&&}4^3;bWW|_v*`hp9=`Ao+7m>e1Hbv#=AaSSx z{WxJVPELRAk66u%)aF4^)Km@bc5`;r`vj{Y#DtA6GaQawj&{g<&sv>N)xpou-)>yW z(B>=W2h~i4tI^{+BS#}86S8t32leeCAg@rNS*7!PD#$(A&Qh?W#V1EVuK3Ujx3(ek zSKbWWAZM0~pZ5EGiD%x|IVOlT7ab!~b%u`TDtr>Tk8G=aKkz=AvB>TxY+Y5a8wwe$ zdE;##@rgn~PXmhmC**i#`RkTX!RvQASVOX*5~7*1C_9uP)AH*p+9i6oxczU$zy(Jv zfz@8|W}Y7l$mI{8_l${H>zpVhjO*}euCA^I=%}5kR?8kDw)j2|=ur%|dIySQ%zQ8+ z&b^D8O>xzDR^uv51J$pxM>~_e)-R*=8)z}t=$=DD1iL!n~TulUlN& z01G*sp%k#6ZnSWvYs7g1wRUXPjO*y=ftmW2UmGk<-~3^EBVxzU{YgssH-;)biVTxn z@(lg<8Mzq~`<9uK2nh*Mj#WM<5Gt2937>T-I5gxu-U#vD^_dZ$64*BxS#%hD@f;|_ z9F;Cn>ViK_&Vo&}-BAOkMH_O)?>2&TDT8g|%}alma#!eepbyG9o8Dr{S!J(OUU4IG z1yax0pSDkToNR4WycE6P3b}soG2TsC#a~OUvlOVaPJKl)?YTnguHqqP9>rsNn|qRNn);2~ z@9F^VfQyPFhLYxH4xFWGW;j^tSo?pyJUD~Ybx6g0?K(5R=z%=9i;Owzis8I-P;^o> z)mp29EyOyygR}q=4(qFzu!1mN4#p8J0b2rJuVunL!R7XEAkoWyp%sXnzWL^KIWd~J z17@q#D35=%8TZFWZ6{s^lt^}qkY8qTp#=~8W7;@Kig>;mXU8cR5r71l9Yaha^>mHV zao%y{XKC`5&{opNBBC2eUp8~fK~91Q8BfOWu{w#U4r%CPBLW%2M3!QM^2F2B&vqwq zaUBYV-h|X~Q|ZH>7aAJh%~Ww}P+d#C!*`eQZ^i~lj((>LAnu-TeA_VpCV|?-w<#>; zWM0L7BcH*F9qaQu^=iB!M{HHEO{86i^_Nws3E&D^LbkM1RvEg!x~K-2bKcV{oN9=R z3Tl-zVn23DKIq%6n}QWwg-S@Msu-5DyQt{-DwzS_j~Ee2XIbYD(Llr**lQsx6+xvb z$eXri+=k&mG>-boPX>+h9Po~P&CB$?ls@hA}4D@KMlm;Bx0(GKinw z#Aqv^ZC`zJorycIZCJFNecGcg*qZ1bn5iG86eRM~17}O0T0a5Xm;%FR-axnh)i`5@tHTUj6>f8@;=V65&e>D+Rt4o6`5#a=^J0m4Px(d17e z=9UX)yAW%n-9=f;V_oKs-@NxqWy%Y20_YcyoGhrfD-M0_t1BM*a;$XFdhH}Y4Kms+r zVguLE)8LHk)O-r6SSq&ilc~Mt(6K!Q|8zsoNxB58_Lt>JwLOGhsSv*%zQ@Po5iQ@y~nN;L9uC9+6n9?qjnjvdCzgQ&|Bl3Bvuve4T z4+zNH<5skSO7N|xIUXz{GMyrq-K;UGrxo4}iLh#RTp_$D0k||@0UI2a!ax_&c@qGU zw3os@kv0p=+(iEKN?T2)!ul%w>PU>gs^aHWOK_#DmO$nn4dXSY7HE~_jy+J2aICT- znCSO>lycZ=GQa6l;|%|lrZ|ruBgV{`xKo(8HMdM(`8^l)alDR^OZb7jOkf z+&k{N*pvpe<6>fLyky--P{ zprfEL^S}&j3%(s+9CV;)8kLy~sQ@#fII$N9c0s-)Brp(~JH!VTY2QTr3difa}XcY#HyjOSSE zo{Z-+1l3Ig%^uDHWI3di5i{6^nWO$75l2X1IC0lciYk6C$$n5$ZGgd!%H(2gvnw5< zEsZy4?N3FMr%1O~T+d47_HtS#3F)k{-EX9EqnLj5hRWbIE ztgkw)F3)+kqn2viA|qrPc*jX*1tZ$Kfs=3}G86QD!2~-%svvMxjUzUzzOy&uLlk*6 z)+?xELmKK2^G$|VN=NW6O)b2T-Wr1F^7jS|+h59bhAZEZqRlij7xwm+7Ba<+WZ%k= zz52F`gf9(W4hN4l&Rhre>OhU`T32g^6OUn4VSjB~b{_^s|`}*$QEzAuO@kYKqH5W(G2UNp*eZ~nq z-lDFKeT*mfBwgm;$OuCAS5S!<4Rr#Dbrg2{Uo=}gSu_YM>xtO{4lFX*(LzD`J74To z>S*M4I{VwNBhaM1I-edawZI;uwpnA)vl3(7G^cSUB;S3fx-K|_)`3#GDaB5Af!n46 z+%|qCY$=0@DMI;ieaE^WHsa^6pe)n#_5G%+iH*tKj9gejKTTG!eq}wxNho?p6Rrjl zkR{yNT|zM%UDsWq+a}VGidGYD3;6Mu4g>wvgHcm=l}l9vq>W8(0crrziCyz1<{Pl_ zIDxL{TUd{I?Lldvgp3jSu`+?v9%$I(Eo&iG@xO93_#iKcY|;|X%$IN5uRWRJ($dAj zTMlUuKeE97{?tm{yCL>va(Q3XpcXJ4;$^wZSuP<~Xz{?$5UvIx-zL*PO{~|ZOj~dp zuKCr#FdzENwZ{Z_QD0EhUk)#=;|0?ZVYr)fw^{@9S!^t8!)?~rwHts?ca$+dvZk$( z96Bak*`Sf~E{sSjEa(Z1t>5zDPBz!e$jq!y5>wDS3VP^k__uAam z>g!x3&9`=wD9a@{Tym86b&s1ULwXNLVno#b-W;&OiL`9q6q&cfXwf&4H3Pf*szoE8 zwI6&TSS@Hkm5E4@rNQfS-XdopvXjQHBj6<5pkNj6fYPa*9As6op2x2#MLZhpH@5zg z+4ti^jkd;v_EFNYTzffTE66YR?h43hH%A9wm0Ikix_I|a9mZ9}$|3YJ!fH45>|gtn}z&qkLMAKA;EFGlB5;5;TrqY_Mo}m6+l#BOrf65f-c_lhU0aoRAem8j@a8|xJmb_ddZn$* zSLr>09$bjIQ`6AGqkR1=$*69l%Y_y3)-BQ3-ANy(|p7Vcmeo^~5rHOGb(RDFG9)Qb=~`PNOh7DEAl zrep4}oz<+tCpSw<-etzt{0J3+?2 zG~!Q_2|G2o zda7H%?vPKDT>kq;zdAV_RCU9_y7CBgk)B`>~{J89iK}wLPZ{jnbJDe$@HTlpQ(qdSzS_`F1Nz{S^T* zp~EfBpB1tS*WKoLkD|1bCL2$r)M!rlf}#aCr>;8)*e|>KJ!K4$8eWAe(NIQgv>UhrX`(^6d^PcWJ}XeiMf`1YnKQ#juG$HZ{c$c-dRZFEa^gKh$ylI9Sa_U_Loj>VBq}aG;SEvHBssS&y1VirJ0E)T zw2>2-ir;r%%Mwb7x~^JWL$d5eQ(w!CuX5#6)+>Q0gLAqiU%*-hDze^688riMKn&*O zderR6<0mU&J}}#xI;lq4_>vU?7P^}!Fv^2P-) zZ8%jgb+YwQVe)i5tOaDGf0jCn`f5F}35o&m1);sJkd71%il02d$?s|t;QLBWfmuLb zXTW$+Q_P_|eg$g=30%C4h*ASd)a!tCAcpc@DE_3DL1p#K)Hsdqu0z(mrYXCSF_cN} z0dH+IRf0}%gNGrzTxV;EgxJ=8+@c$v%2Ol8$*sgM-i+o|&)K>2#GuP>qva|O&9U%| z;kbMqV=u_ckBf1k62dxOyJL{=JYXB7NOW$cp!Omn7}Viw`#rM*D|rnOcl1sKt^qOF ze~ewjn`yS&m@F~m4vG5RLLi``cnf8>T}a8_;kHWH=?B|%2x)q&$$gpdX!J1_7@5Cw zq-A(K6MFCyGFWjZYFit`_0qW=%8&zaHg)Al<~rNmHd#F@=>0M$Z2YBAff(9` z$VGem!Meu#(T)ES461>!{cDp$Df#Y+Q7iUuLAK!oR$sO_h9EP|Z#RzWE}>BjmrVV&{o4w(Xvj;`NG%XJSu z3mpq&4G5fk2~=&26r(L8E7FCw!W8`T7}pADh7C1E0q}w>8Yw-i0L2mES3qb62hr&$ zQGe2H4vdIk+nh9<%&QiVQK9SD6v&kY|7gABNfhdv)} zJp7KS6HP&ouGgf5=lv7g1?4%2uSu?g@Olu0cyNDAL|y)XhS$ylz7#&O;IggNQBkF* zOSoowI;WbOOE|f}zOemN_u>3>rJOhR4E2$;pttNsN)T6%*3fWrMla@PVG(S+Ag|5i zt}X}IBBz@UNctHUl?5{=4ffW(?1LdI#PwUj01Ih8EFAp1!t}S`zt~7lIG`FtBTJ+Y z+c+k|Som^6ob#-VH}3NIEY)j={PMTPv<>KcX{qdcfM`3T0X5IoP0&5tMkU0HgC6xz zWVsFI2SypF3N-rnFk;~nBkRvu*6`h4@LAS*Ew8M9q=cxNVH< zN|-}2XiFtv_WDG6A1*x56>;aNz_Q$KY4O>=(TkoJ(1l+EgpT67O^!p@k79HXMRu>qEc~Qg7E)b9 zvzflOGL|Ei&1b)jCGeJCa5H!gXFr5p*2EinpX(F!Ib{n;Aj|C={ELT&i*7kJxf9bo z|6r13l5N6YqLG|(IByavhcX?6pBkYWgYG>U*C;Am0?n!3x3|C5c+BJ7`36~$|6_eZ zb#R~#)U=C?2_kFSFKtW!?P4n#l2fjDVK2gz?(tm1q|yGG?SL!nwuk@)_vR|8Xyc*M z+-oC~5Vf>h0$z;~voZebg1I42p51KfWjV2tfl5PVp*ibC1OCgOmP&;-KEQnY@p#_A5ee=`~`El->} z9PGFAnl3C)m|||yt|$r?f4}cv4@ehQm{euxgWg>Tq9)`XwVWooDk-NOj_k{cnCQnGWM+Fa(q`)t4^lFH7TO!rtFRtDj zVaH7Ng6~5r7-A~so*On4nA9Fc-&h7zNEZ_7e`5Bv+yke)?EqAmy(Q|Ue{w@~3-i)5 zW=yS0OyibLy$p{jDmVm>mJgSprXF>pND>69tzA~ki5=C`8H}_Y3ki-hpiT5B-Rc_MPje-3 zF`>AOY%PN2re`wux1_hf0dfYg1sG#^Jj$iFxja&qZg;0ReP9Mjh>4xxD!!!Ph)0o- zn^rVh9PuL=6Wv@2=ZM!lfAjQ6Y>zHjde&~cI5XJFixE5};(#*d(Fs823wo7U-n}0z z)h;`Xf3x(w2W&3fC$@g>!@?_R>bV-vwlKHa&Q9kmRac6D!3&@&b;D18!A>?CCKsjb ze|eW8ri%3JOSe}Bb5gDY0-ujFYi@#6t$6}le$2o8P*fh*Hq41EW5Tnak8;%?FI8nE z*p(Oh%vCmJy4jmyHBbV=*Qf_67vN}Jm~0dkIEYQhuRMfREmZRV#V#Q6`)>TK>oGN3 zcM0GC{09Z^4{?w8!k9kf$?;eq0Nlp%C;tbQ9Z0Q_I^kpg3-b*~I6W-?pKVN#r6Ya) zSE%BVgb@ozw!)1%{W)gKF}oz>_0+)&K1KyBEc=2x)}L zlP7J*M=K>i$KonqOq8WkU!0B~)y7Y4J6*v-p2_jg(J@Twpk!Q&26=cjpT?0f;Dwvh zhd>d&;_R#7EXhNwnJU%j0f9>bHa2R2O2 zFslE>_QLGm>_v99hM1*Sl{xBG|2><4i&tTmZUO!*}oV)BTz|IN-QEZho~9 zw^U>`QbZm?W==ClCAK8%ClS(FgS1LBSMA!0##Dl#4~wB(kFzB>0R`?0zVO^%zb0=p zhg5#Q|H4mdA2H$zsR1N<;{1}8;yTVk8M8W8ZT`ATWwX%f?#LEl z!#n%2M_OTg{X+EMcv08&c7`NS(1%7V|`jNlso!owYGug}7W6Ak4W}{E-Q*R)z znSb>H6wd|GE?^5=q2lIWyEuS=9DFH>07?cIsP{{tX@ER@87P8-Lg9>lBp{v#^ahYe zi7nm!Q*4IR(fh}7C;+$xlG@-C4fR{d!uJc=zgyhkgO?saH5_am0WG5pAT#lgPmq!l zGKeaRfi&{pt;pP(rfhR&E`1OD6e*Anl!+}DH&M*Jfd{tGeF%}|^#A1=U>6b`HA?)C zx@kP{K?V@^Hw9T8=ok%wzaIeJ?aV$jDoM8ibRhu9UIF~(|8X!f1(Y-bAD|$B(>=uj zDT?2fZVXi9kVE#uCHFx8R(8zsM{;f>$#!*LR-gQHYlknN+N(nFM)rkOD5Zb;c%+b1 zaVkIEwQsSdq6@ZPVMF_8-vAs(j&GHKtLyxukWEExKLl4o%%-CB?h{ZXJ2YRDo_{Wi z6=^5BUR{9xuhY=MY5D|t@6(x5ie6>OhT-c!1b&&Tr;LN`-{ieE2yM%TWvk4ramT=`hq(Xj0%UE@?UXQbGOP$m zBTG~%1)T8BDeNO%Y!U>eT*!^cbZWZmU6W08XL<_f|LS>pzr3W-z~(QBEgCZi(nb~g z`|1JP6$5IhZHDU`0cj1~=t_6~bJ&!8QgWjQh8J{B3a}+Z`d(=L$5gp+fy_5OTkaFVf*r_l)rP45N}WJZ#_kHzQB`J$6x0 zv+t?+@vyrc91-xSfUCQ-lvC{Sk+*DbK4wKXM~+04L9suhRW6I@Ch#eGjE?7so$~-`<&kFs*>pJ7wexQw&}xU zZTQ^#E2eKwdp(YNSW|k6F6hl&_`wX?ag6<^8dd`NikM!sw1C4RemcMJ6Mjdtb`sO} zJqtX>7U6H0IZt3H{5N`$zg#d9C6|CAlK>sDXOb*M*Jp8=%(n?)#j(s5nN|C~i>zFk zf<(`x&&COOZtpToGwOa7!ou^GXnE_)N(>W7gDb2E(`IG&aV9psl~$p=ci*_5DAsbv zSQ=IRxM&b|%lt?H|N4+gPbeA6O%PrfuJ-7l?;;~VJBCRk?*j&`s(d;{IGeV8HuOsy6bHDGQ^zXDEz?d z`!DJU-XQ00AU{LwogVkF)hMT*UsZxxzK;{zRjMf4&~Fhy(0%;Zm{tIEELB#7RUPY- zzmR(h6cxy(CT~_c>Dt`nA2_^)MyQ0prvUn77R6 z-TY`z#}h)NnOV4tvxK-&gX3kuz(PT;OhC&U1(0E`Oe@0Bg44c1(WT2$8l#C!mHZKA zVQXd%)N6)Z5XL^KByA!NV#l?_LiFG?IK?@BoSSdbuHhP=$_c`HRNM*Hi%5;9pi>sT zUUvh}*AokG5aZ9>a`_lraf9t+wp5IMZ(IGxZ*)m8QHH)hxW_ow#Vb49B->gTcrTPT z@%^{K3CE@d+I`}K_Yp+;@W7tR9}?Q~Q0lb_0!$n=f)6-&_(k>9G^7@a`OO)p=3xpb z?=Dw%Oni6OsBiS{SHfc8OEh0`CEn*&@iYw=#WP7{FiCvQ-D|Va1+yLKPT5Hp3>oFU zYfqmNF*bkfvJHb9(;g(Nj*5+LPqK$SHaIPcz?<%epxmdFxe^~vy#s*z!Hq8KEZ!g0 z8|elT;-#>44RsWL^xuO`ej*eXZ>MJltclMmI1`$=_h?WrR^*rK7yXMY8o3#(eXyjy zWT;OWNe1mQyV8#;0}~f7;5n+1xmeCo21);3w)E+V&_mFwd4j4H(W@0sFQ(!5dg$_Q zo{ta~Y(oE9|KT^^F_XK5l8`S8umI~CbxJ(kK>q?j+QqFdfc#$e|3o)V*Yru?=lC|Z zboLqMbd>1w2Pc34hg=AhE?4`PK+HCxhFQbbQ{+d@x4patd4+0`AZc2UD!RS#kDKw# zCKxiO`h35eFbsHUe>C{PxC=w2OU%57g|}8&KCPSEY8IAsosN?i(0PzI_>6w}i$TrS zB}bKkper$RqtXLO$9D5O4|*P*x7hx34F*W`XF$WtO2PvEHXI9R!Hs(KTbbfv;&FsV z>jnOof?$^|*YLias{tJWROSUBEijBQF2j|?mj5oM19cH#ll{NM3jg16)n85`|GC2d zzXpc?3N0|0seX5m6JVREavq0I*CIbq#kmSXdO{ zL*5ER=4!4)B5m^yp~i2qzMR@@kP(qVY%|@IKs_)#=Pv#N8IBiFV=ruEzWxUhy{)mw)SijM9ZeRs#O#O2Suk9`-hx-1q0l`8Dn@wYE zLs=A%Tv}e92-meCNVnbH+2t+b27uj4QFS;n2kc_cBYUX+(6GBVxY}ZXdaDJK=2PlT zWOI)2Z>B#>sVW_dV+@T+_hgK9qlEVDc*@T|swd7I%=aL8+ z#CwW~P5AfHixd#3OrfB3hjjj=5_LhNuS{+5Ir=z%%%N-C#RPO9mw!RV1jp*irg0<9 zdg8;%`$ZyDt$r(Efh-T^bIf7$78P89wY|!E=EuRR>G3{psi!OZ6*=%?W&x+@kimE& z|E<(j%a_f!bZhJ~Rg6m-_MQl|pr2mt)6;0sI8BTn-)uZPdcnfW9f!;#c4_#pkGR!8 z8_6*Wbg7{62@S&os@9v2 z7v#Kx(IIW0<2F)Y$#Qmdbv9*+|E@SH|2%mGf7w4 zuz6Qln5#{VffskBf>)_k(t&x~k=yHKEVN+Y0V#*5a@;cBI(yS4?R6&HfWe>l?LFzR z4Q1hldX##q$RnS~m_|ym=cCL#z(H@2fw_^yg6QT*j%xYyhgH{N48p2iHw+H#X*{qf z!M#yBWER+?s(%$&MktX;80;3<~m8tZ}d0wNnKr)1f Q0r@zJa%!^0(nkLO2S_@VM*si- literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..2530106 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# 项目简介 + + 本项目是基于STM32L072开发的控制器。 + +# 目录说明 + ++---application 应用层,需要实现的功能 +| +---inc +| \---src ++---board 和开发板有关的设备驱动,基于BSP或者LIB中的模块生成的驱动 +| +---inc +| \---src ++---hart HART协议相关 +| +---inc +| +---master 主设备协议 +| | +---inc +| | \---src +| \---slave 终端协议 +| +---inc +| \---src ++---lib 通用的库,和硬件无关 +| +---control PID控制器 +| | +---inc +| | \---src +| +---flow 流程控制 +| | \---.vscode +| +---font 字体 +| +---inc 通用头文件 +| +---lcd LCD显示 +| +---menu 菜单 +| +---src 通用源文件 +\---system 系统层,和硬件有关的驱动 + +---bsp 板级支持包,基于LL库开发 + +---inc 系统头文件 + \---src 系统源文件 + +# 架构图 + + + +# 未处理问题 + +1. 开机通电时间 +2. 全开全关时间 +3. 蓝牙在手动模式下使用 +4. 控制满足条件 + +a) 位置起动时间与信号给出时间的滞后不大于1s(25%阶跃); + +b) 最终定位与信号要求位置误差不大于±0.5%,稳态时间小于2s; + +c) 调节过程位移过冲不大于1%; + +d) 动态误差带小于5%; + +e) 动态线性度小于1%; + +f) 满足振动(包括管道内波动)试验要求。 + +g) 需要考虑不同的摩擦力 + +# BUG清单 + diff --git a/Tests/.idea/.gitignore b/Tests/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/Tests/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/Tests/.idea/Tests.iml b/Tests/.idea/Tests.iml new file mode 100644 index 0000000..4c94235 --- /dev/null +++ b/Tests/.idea/Tests.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Tests/.idea/modules.xml b/Tests/.idea/modules.xml new file mode 100644 index 0000000..cdb507c --- /dev/null +++ b/Tests/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Tests/.idea/vcs.xml b/Tests/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/Tests/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Tests/Makefile b/Tests/Makefile new file mode 100644 index 0000000..cf6b4e4 --- /dev/null +++ b/Tests/Makefile @@ -0,0 +1,61 @@ +BIN = run.exe +SO = lib.dll + +SRC = \ + ../User/lib/src/malloc.c \ + ../User/lib/src/sqqueue.c \ + ../User/lib/src/mlist.c \ + ../User/lib/src/debug.c \ + ../User/lib/src/data_analysis.c \ + ../User/lib/src/filter.c \ + ../User/lib/src/clist.c \ + ../User/lib/src/aes.c \ + ../User/lib/src/cmac.c \ + ../User/lib/src/lib.c + +EXAMPLE = \ + ./test_hart.c + +CPLUS_INCLUDE_PATH= -I ../User/lib/inc + +# 变量CC:给定编译器名gcc +# 变量CFLAGS:传给编译器的某些编译参数,看需求添加 +CC = gcc +CFLAGS = -m32 -std=c99 +# 变量GDB:给定debugger名gdb +# 变量RM:给定删除文件方式,用于后面删除所有编译所得的.o文件,linux下使用rm -rf +GDB = gdb +RM = rm -rf +# 变量OBJS:将变量SRC中所有的.c文件替换成以.o结尾,即将.c源文件编译成.o文件 +OBJS = $(SRC:%.c=%.o) +EXAPMLES = $(EXAMPLE:%.c=%.o) + +$(SO): $(OBJS) $(EXAPMLES) + + +# pull in dependencies for .o files +-include $(OBJS:.o=.d) + +%.o: %.c + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) -c $< -o $@ + +.PHONY: all clean clist data_analysis + +all: $(SO) + +rm: + $(RM) $(OBJS) + +hart:$(SO) + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) $(OBJS) ./test_hart.o -o $(BIN) + $(RM) $(OBJS) $(EXAPMLES) + run + + +#运行程序 +run: + ./run.exe + +clean: + $(RM) $(OBJS) $(EXAPMLES) $(BIN) + diff --git a/Tests/board/test_eeprom_fm24.c b/Tests/board/test_eeprom_fm24.c new file mode 100644 index 0000000..6466df3 --- /dev/null +++ b/Tests/board/test_eeprom_fm24.c @@ -0,0 +1,41 @@ +#include "unity.h" +#include "eeprom_fm24.c" + +void setUp(void) +{ + // 这里可以进行每个测试用例开始前的设置 +} + +void tearDown(void) +{ + // 这里可以进行每个测试用例结束后的清理 +} + +void test_eeprom_fm24_write(void) +{ + // 测试写入数据 + uint32_t write_addr = 0x0000; + uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05}; + uint16_t length = sizeof(data); + TEST_ASSERT_TRUE(eeprom_fm24_write(write_addr, data, length)); +} + +void test_eeprom_fm24_read(void) +{ + // 测试读取数据 + uint32_t read_addr = 0x0000; + uint8_t data[5]; + uint16_t length = sizeof(data); + TEST_ASSERT_TRUE(eeprom_fm24_read(read_addr, data, length)); + TEST_ASSERT_EQUAL_HEX8_ARRAY((uint8_t[]){0x01, 0x02, 0x03, 0x04, 0x05}, data, length); +} + +int main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_eeprom_fm24_write); + RUN_TEST(test_eeprom_fm24_read); + + return UNITY_END(); +} diff --git a/Tests/board/test_eeprom_m95.c b/Tests/board/test_eeprom_m95.c new file mode 100644 index 0000000..0a2743d --- /dev/null +++ b/Tests/board/test_eeprom_m95.c @@ -0,0 +1,113 @@ +#include "unity.h" +#include "eeprom_m95.h" + +void setUp(void) +{ + // Set up code here +} + +void tearDown(void) +{ + // Tear down code here +} + +void test_eeprom_m95_read(void) +{ + // Test case for eeprom_m95_read function + m95_number_e num = M95_1; + uint32_t read_addr = 0x0000; + uint8_t data[10]; + uint16_t length = 10; + + // Perform the read operation + eeprom_m95_read(num, read_addr, data, length); + + // Add assertions here to verify the correctness of the read operation + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_data, data, length); +} + +void test_eeprom_m95_write(void) +{ + // Test case for eeprom_m95_write function + m95_number_e num = M95_1; + uint32_t write_addr = 0x0000; + uint8_t data[10] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44}; + uint16_t length = 10; + + // Perform the write operation + eeprom_m95_write(num, write_addr, data, length); + + // Add assertions here to verify the correctness of the write operation + // You can perform a subsequent read operation to verify the written data +} + +void test_eeprom_m95_enable(void) +{ + // Test case for eeprom_m95_enable function + // Perform the enable operation + eeprom_m95_enable(); + + // Add assertions here to verify the correctness of the enable operation + // You can check the status of the M95 EEPROM to ensure it is enabled +} + +void test_eeprom_m95_disable(void) +{ + // Test case for eeprom_m95_disable function + // Perform the disable operation + eeprom_m95_disable(); + + // Add assertions here to verify the correctness of the disable operation + // You can check the status of the M95 EEPROM to ensure it is disabled +} + +void test_eeprom_m95_init(void) +{ + // Test case for eeprom_m95_init function + m95_number_e num = M95_1; + + // Perform the initialization + eeprom_m95_init(num); + + // Add assertions here to verify the correctness of the initialization + // You can check the values of the initialized variables and perform any necessary checks +} + +void test_eeprom_m95_dinit(void) +{ + // Test case for eeprom_m95_dinit function + m95_number_e num = M95_1; + + // Perform the deinitialization + eeprom_m95_dinit(num); + + // Add assertions here to verify the correctness of the deinitialization + // You can check the status of the M95 EEPROM to ensure it is properly deinitialized +} + +void test_eeprom_m95_test(void) +{ + // Test case for eeprom_m95_test function + m95_number_e num = M95_1; + + // Perform the test + eeprom_m95_test(num); + + // Add assertions here to verify the correctness of the test + // You can check the results of the test and perform any necessary checks +} + +int main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_eeprom_m95_read); + RUN_TEST(test_eeprom_m95_write); + RUN_TEST(test_eeprom_m95_enable); + RUN_TEST(test_eeprom_m95_disable); + RUN_TEST(test_eeprom_m95_init); + RUN_TEST(test_eeprom_m95_dinit); + RUN_TEST(test_eeprom_m95_test); + + return UNITY_END(); +} diff --git a/Tests/board/test_ntc_3950.c b/Tests/board/test_ntc_3950.c new file mode 100644 index 0000000..7a28689 --- /dev/null +++ b/Tests/board/test_ntc_3950.c @@ -0,0 +1,42 @@ +#include "unity.h" +#include "ntc_3950.c" + +void setUp(void) +{ + // 这里可以进行每个测试用例开始前的设置 +} + +void tearDown(void) +{ + // 这里可以进行每个测试用例结束后的清理 +} + +void test_ntc_lookup(void) +{ + const uint32_t table[] = {8989000, 8242680, 7592960, 7021380, 6513750, 6059060}; + TEST_ASSERT_EQUAL_UINT8(0, ntc_lookup(table, 8989000)); + TEST_ASSERT_EQUAL_UINT8(1, ntc_lookup(table, 8242680)); + TEST_ASSERT_EQUAL_UINT8(2, ntc_lookup(table, 7592960)); + TEST_ASSERT_EQUAL_UINT8(3, ntc_lookup(table, 7021380)); + TEST_ASSERT_EQUAL_UINT8(4, ntc_lookup(table, 6513750)); + TEST_ASSERT_EQUAL_UINT8(5, ntc_lookup(table, 6059060)); +} + +void test_ntc_get_temp(void) +{ + TEST_ASSERT_EQUAL_FLOAT(0.0, ntc_get_temp(4095).f); + TEST_ASSERT_EQUAL_FLOAT(-55.0, ntc_get_temp(0).f); + TEST_ASSERT_EQUAL_FLOAT(-54.9, ntc_get_temp(1).f); + TEST_ASSERT_EQUAL_FLOAT(-54.8, ntc_get_temp(2).f); + // Add more test cases here +} + +int main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_ntc_lookup); + RUN_TEST(test_ntc_get_temp); + + return UNITY_END(); +} diff --git a/Tests/board/test_rtc_rx8010.c b/Tests/board/test_rtc_rx8010.c new file mode 100644 index 0000000..7fd869f --- /dev/null +++ b/Tests/board/test_rtc_rx8010.c @@ -0,0 +1,98 @@ +#include "unity.h" +#include "rtc_rx8010.h" + +void setUp(void) +{ + // Set up any necessary test fixtures +} + +void tearDown(void) +{ + // Clean up any resources allocated in setUp() +} + +void test_rtc_read_byte(void) +{ + // TODO: Implement test case for rtc_read_byte() +} + +void test_rtc_read_bytes(void) +{ + // TODO: Implement test case for rtc_read_bytes() +} + +void test_rtc_write_byte(void) +{ + // TODO: Implement test case for rtc_write_byte() +} + +void test_rtc_write_bytes(void) +{ + // TODO: Implement test case for rtc_write_bytes() +} + +void test_rtc_dummy_read(void) +{ + // TODO: Implement test case for rtc_dummy_read() +} + +void test_rtc_check_vlf(void) +{ + // TODO: Implement test case for rtc_check_vlf() +} + +void test_rtc_wait_vlf_clear(void) +{ + // TODO: Implement test case for rtc_wait_vlf_clear() +} + +void test_rtc_soft_reset(void) +{ + // TODO: Implement test case for rtc_soft_reset() +} + +void test_rtc_clock_reginit(void) +{ + // TODO: Implement test case for rtc_clock_reginit() +} + +void test_rtc_init(void) +{ + // TODO: Implement test case for rtc_init() +} + +void test_rtc_dinit(void) +{ + // TODO: Implement test case for rtc_dinit() +} + +void test_rtc_get_clock_time(void) +{ + // TODO: Implement test case for rtc_get_clock_time() +} + +void test_rtc_set_clock_time(void) +{ + // TODO: Implement test case for rtc_set_clock_time() +} + +int main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_rtc_read_byte); + RUN_TEST(test_rtc_read_bytes); + RUN_TEST(test_rtc_write_byte); + RUN_TEST(test_rtc_write_bytes); + RUN_TEST(test_rtc_dummy_read); + RUN_TEST(test_rtc_check_vlf); + RUN_TEST(test_rtc_wait_vlf_clear); + RUN_TEST(test_rtc_soft_reset); + RUN_TEST(test_rtc_clock_reginit); + RUN_TEST(test_rtc_init); + RUN_TEST(test_rtc_dinit); + RUN_TEST(test_rtc_get_clock_time); + RUN_TEST(test_rtc_set_clock_time); + + return UNITY_END(); +} diff --git a/Tests/test.c b/Tests/test.c new file mode 100644 index 0000000..68d19fe --- /dev/null +++ b/Tests/test.c @@ -0,0 +1,19 @@ +#include "test.h" +#include "test_bsp.h" + +void test(uint8_t flag) +{ + switch (flag) + { + case TEST_DISABLE: + return; + case TEST_BSP: + bsp_test(); + break; + case TEST_POWER: + power_test(); + break; + default: + break; + } +} diff --git a/Tests/test.h b/Tests/test.h new file mode 100644 index 0000000..503ab13 --- /dev/null +++ b/Tests/test.h @@ -0,0 +1,16 @@ +#ifndef __TEST_H__ +#define __TEST_H__ +#include "lib.h" +#include "bsp.h" +#include "delay.h" +#include "main.h" + +typedef enum +{ + TEST_DISABLE, + TEST_BSP, + TEST_POWER, +}test_e; + +extern void test(uint8_t flag); +#endif // __TEST_H__ diff --git a/Tests/test.py b/Tests/test.py new file mode 100644 index 0000000..c4fa620 --- /dev/null +++ b/Tests/test.py @@ -0,0 +1,3 @@ +hex_value = "0x65EADA6E" +dec_value = int(hex_value, 16) +print(dec_value) diff --git a/Tests/test_bsp.c b/Tests/test_bsp.c new file mode 100644 index 0000000..fb36c14 --- /dev/null +++ b/Tests/test_bsp.c @@ -0,0 +1,781 @@ +/* + * @Author: xxx + * @Date: 2023-08-04 08:48:56 + * @LastEditors: xxx + * @LastEditTime: 2023-08-25 14:38:40 + * @Description: 此文件为驱动测试用例,用于板卡驱动测试 + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "lib.h" +#include "test_bsp.h" +#include "entity.h" +#include "board.h" +#include "rtc_rx8010.h" +#include "eeprom_m95.h" +#include "eeprom_fm24.h" +#include +#include "flashdb.h" + +#define ADC_MIN 100 // 有效ADC最小值 +#define ADC_MAX 4095 // 有效ADC最大值 +#define VOL_DIF 0.5 // 电压稳态误差 + +uint8_t test_buf[10]; + +/** + * @brief 测试GPIO是否正常工作 + IP输出使能 : VIP_EN_GPIO_Port, VIP_EN_Pin + IP大电流输出使能 : IP_H_PWR_GPIO_Port, IP_H_PWR_Pin + * @param {GPIO_TypeDef} *port + * @param {uint16_t} pin + * @return {*} + */ +BOOL test_gpio(GPIO_TypeDef *port, uint16_t pin) +{ + uint8_t ret = 0; // 临时变量,用于保存返回值 + + GPIO_SET(port, pin); // 将指定GPIO引脚设置为高电平 + delay_tick(10); // 等待10个时钟周期 + ret = GPIO_READ(port, pin); // 读取当前GPIO引脚的状态 + if (ret != 1) + { + return FALSE; // 如果读取到的状态不是1,表示设置失败 + } + + GPIO_RESET(port, pin); // 将指定GPIO引脚设置为低电平 + delay_tick(10); // 等待10个时钟周期 + ret = GPIO_READ(port, pin); // 读取当前GPIO引脚的状态 + if (ret != 0) + { + return FALSE; // 如果读取到的状态不是0,表示设置失败 + } + + return TRUE; // 设置成功 +} + +/** +* @brief 这是一个用于测试ADC读取功能的函数 + 测试ADC,通道使用如下: + 回路电流 : ADC_LOOP_CHANNEL + 阀位反馈 : ADC_PSB_CHANNEL + 阀位反馈-小回路 : ADC_IPSB_CHANNEL + 气源压力 : ADC_BP_CHANNEL + A路压力 : ADC_BPA_CHANNEL + B路压力 : ADC_BPB_CHANNEL +* @param {adc_num_t} channel - 指定ADC通道,通道使用如下: +* @param {uint16_t} *adc - 存储读取到的ADC值的指针 +* @return {*} - 返回一个布尔值,表示读取操作是否成功 +*/ +BOOL test_adc(uint8_t chan, uint16_t *adc) +{ + uint16_t tmp = 0; // 临时变量,用于存储读取到的ADC值 + + tmp = adc_result_average(ADCS_1, chan); // 读取指定ADC通道的值 + + if ((tmp >= ADC_MIN) && (tmp <= ADC_MAX)) // 判断读取到的值是否在允许的范围内 + { + *adc = tmp; // 读取成功,将读取到的值存储到*adc指针指向的位置 + return TRUE; // 返回成功标志 + } + + return FALSE; // 返回失败标志 +} + +/** + * @brief 这是一个用于测试IP输出的函数。 + * @param {uint16_t} value - 测试的DAC设定值。 + * @return {*} - 测试结果,TRUE表示测试通过,FALSE表示测试失败。 + */ +BOOL test_ip_putput_dac(uint16_t value) +{ + uint16_t dac = value; + float32 target_vol; + float32 target_cur; + + uint16_t adc; + float32 actual_vol; + + // 设置DAC输出设定值 + dac = value; + // dac_output(dac); + + // 计算理论电流ma + target_cur = ip_dac2current(dac); + // 计算理论电压v + target_vol = target_cur * 10 * 101 / 1000; + + // 读取实际ip输出 + adc = adc_result_average(ADCS_1, ADC_VIP_CHANNEL); + // 计算实际电压v + actual_vol = (float32)adc / 4096 * VREF_VALUE / 1000; + + // 判断实际电压与理论电压的差值是否小于允许的误差范围 + if (fabs(target_vol - actual_vol) < VOL_DIF) + { + return TRUE; + } + + // 测试失败 + return FALSE; +} + +/** + * @brief 这是一个用于测试IP输出的函数。 + * @param {uint16_t} duty 占空比 + * @return {*} + * @note + */ +BOOL test_ip_putput_pwm(float32 duty_percent) +{ + uint16_t adc; + float32 target_vol; + float32 actual_vol; + target_vol = 6.2f * duty_percent; + // 读取实际ip输出 + adc = adc_result_average(ADCS_1, ADC_VIP_CHANNEL); + // 计算实际电压v + actual_vol = (float32)adc / 4096 * VREF_VALUE / 1000; + // 判断实际电压与理论电压的差值是否小于允许的误差范围 + if (fabs(target_vol - actual_vol) < VOL_DIF) + { + return TRUE; + } + return FALSE; +} + +/** +@brief 这是一个用于测试DC/DC转换的函数,它接收一个float32类型的指针参数vol,用于存储转换后的电压值。 +@param {float32} *vol +@return {*} +*/ +BOOL test_dcdc(float32 *vol) +{ + uint16_t tmp_adc1; + float32 tmp_vol1; + + // 读取ADC值 + tmp_adc1 = adc_result_average(ADCS_1, ADC_DCDC_CHANNEL); + // 计算实际电压v + tmp_vol1 = (float32)tmp_adc1 / 4096 * VREF_VALUE / 1000 * 2; + *vol = tmp_vol1; + + return TRUE; +} + +/** + * @brief 测试回路电流 + * @return {*} + */ +BOOL test_loop_current(float32 *cur) +{ + uint16_t tmp_adc; + float32 tmp_cur; + + // 读取ADC值 + tmp_adc = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); + + // 计算回路电流 + tmp_cur = loop_current_convert(tmp_adc); + *cur = tmp_cur; + + return TRUE; +} + +/** +@brief 这是一个用于测试温度传感器的函数,它接收一个float32类型的指针参数temp_f,用于存储转换后的温度值。 +@param {float32} *temp_f +@return {*} +*/ +BOOL test_temperature(float32 *temp_f) +{ + // 获取当前温度 + *temp_f = get_temperature(); + + return TRUE; +} + +/** + * @brief 这是一个用于测试RTC功能的函数,它接受两个参数:一个表示操作类型的uint8_t opt和一个指向rtc_date类型的指针data。 + * @param {uint8_t} opt - 操作类型,可以是0(设置时间)或1(读取时间)。 + * @param {rtc_date} *data - 包含时间信息的rtc_date结构体的指针。 + * @return {*} - 操作成功返回TRUE,否则返回FALSE。 + */ +BOOL test_rtc(rtc_opt_e opt, rtc_date *data) +{ + uint8_t tmp[7]; + + if (opt == 0) // 如果操作类型为0(设置时间),则调用rtc_set_clock_time函数设置时间 + { + rtc_set_clock_time(data); + return TRUE; + } + else if (opt == 1) // 如果操作类型为1(读取时间),则调用rtc_get_clock_time函数读取时间并将其存储在tmp数组中 + { + rtc_get_clock_time(tmp); + + data->year = tmp[6]; // 将年存储在data结构体的year字段中 + data->month = tmp[5]; // 将月存储在data结构体的month字段中 + data->day = tmp[4]; // 将日存储在data结构体的day字段中 + data->weekday = tmp[3]; // 将星期存储在data结构体的weekday字段中 + data->hour = tmp[2]; // 将时存储在data结构体的hour字段中 + data->minute = tmp[1]; // 将分存储在data结构体的minute字段中 + data->second = tmp[0]; // 将秒存储在data结构体的second字段中 + + // 判断rtc_date 数据是否合法 + if ((data->year > 0x99) || (data->month > 0x12) || (data->day > 0x31) || (data->weekday > SAT) || (data->hour > 0x23) || (data->minute > 0x59) || (data->second > 0x59)) + { + return FALSE; // 如果数据不合法,返回FALSE + } + return TRUE; + } + + return FALSE; // 如果操作类型不在0和1之间,返回FALSE +} + +BOOL test_eeprom_lc02b(uint16_t addr, uint8_t *buf, uint16_t len) +{ + uint8_t i = 0; + + osel_memset((uint8_t *)test_buf, 0, 10); + eeprom_lc02b_write(addr, buf, len); // 向EEPROM写入数据 + delay_ms(10); // 芯片要求,必须等待10ms + eeprom_lc02b_read(addr, test_buf, len); // 从EEPROM读取数据到tmp数组中 + + for (i = 0; i < len; i++) + { + if (test_buf[i] != *(buf++)) // 逐个比较buf和tmp数组中的数据 + { + return FALSE; // 如果发现有不相等的数据,返回FALSE + } + } + + return TRUE; // 如果所有数据都相同,返回TRUE +} + +/** + * @brief SPI EEPROM写入测试 + * @return {*} + */ +BOOL test_eeprom_m95_write(m95_number_e num, uint8_t *buf, uint16_t len) +{ + eeprom_m95_write(num, _M95_SIZE - 64, buf, len); // 向EEPROM写入数据 + delay_ms(10); // 等待一段时间 + + return TRUE; // 返回TRUE +} + +/** + * @brief SPI EEPROM读取测试 + * @return {*} + */ +BOOL test_eeprom_m95_read(m95_number_e num, uint8_t *buf, uint16_t len) +{ + eeprom_m95_read(num, _M95_SIZE - 64, buf, len); // 从EEPROM读取数据 + delay_ms(10); // 等待一段时间 + + return TRUE; // 返回TRUE +} + +/** + * @brief 这是一个用于测试外部EEPROM的函数,它接受三个参数: + * @param {uint16_t} addr - 要写入的地址。 + * @param {uint8_t *} buf - 要写入的数据缓冲区。 + * @param {uint16_t} len - 要写入的数据长度。 + * @return {*} + * @retval TRUE - 如果写入和读回的数据相同,则返回TRUE。 + * @retval FALSE - 如果写入和读回的数据不同,则返回FALSE。 + */ +BOOL test_eeprom_m95(m95_number_e num, uint16_t addr, uint8_t *buf, uint16_t len) +{ + uint8_t i = 0; + + osel_memset((uint8_t *)test_buf, 0, 10); + eeprom_m95_write(num, addr, buf, len); // 向EEPROM写入数据 + delay_ms(10); // 等待一段时间 + eeprom_m95_read(num, addr, test_buf, len); // 从EEPROM读取数据到tmp数组中 + + for (i = 0; i < len; i++) + { + if (test_buf[i] != *(buf++)) // 逐个比较buf和tmp数组中的数据 + { + return FALSE; // 如果发现有不相等的数据,返回FALSE + } + } + + return TRUE; // 如果所有数据都相同,返回TRUE +} + +static BOOL test_flashdb_kv(void) +{ + static uint32_t boot_count = 0; + /* default KV nodes */ + static struct fdb_default_kv_node default_kv_table[] = { + {"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */ + }; + /* KVDB object */ + static struct fdb_kvdb kvdb = {0}; + fdb_err_t result; + struct fdb_default_kv default_kv; + default_kv.kvs = default_kv_table; + default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]); + /* set the lock and unlock function if you want */ + fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)fdb_lock); + fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)fdb_unlock); + /* Key-Value database initialization + * + * &kvdb: database object + * "env": database name + * "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table. + * Please change to YOUR partition name. + * &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully. + * NULL: The user data if you need, now is empty. + */ + + result = fdb_kvdb_init(&kvdb, "env", "KVDB", &default_kv, NULL); + if (result != FDB_NO_ERR) + { + return FALSE; + } + + { + + struct fdb_blob blob; + again: + fdb_kv_get_blob(&kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); + if (blob.saved.len > 0) + { + boot_count++; + result = fdb_kv_set_blob(&kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); + if (result != FDB_NO_ERR) + { + return FALSE; + } + return TRUE; + } + else + { + boot_count++; + result = fdb_kv_set_blob(&kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); + if (result != FDB_NO_ERR) + { + return FALSE; + } + goto again; + } + } +} +static fdb_time_t get_time(void) +{ + /* Using the counts instead of timestamp. + * Please change this function to return RTC time. + */ + return (int32_t)sys_millis(); +} + +struct env_status +{ + int temp; + int humi; +}; + +static bool ts_query_cb(fdb_tsl_t tsl, void *arg) +{ + struct fdb_blob blob; + struct env_status status; + fdb_tsdb_t db = arg; + + fdb_blob_read((fdb_db_t)db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status)))); + return false; +} + +static bool ts_query_by_time_cb(fdb_tsl_t tsl, void *arg) +{ + struct fdb_blob blob; + struct env_status status; + fdb_tsdb_t db = arg; + + fdb_blob_read((fdb_db_t)db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status)))); + return false; +} + +static BOOL test_flashdb_ts(void) +{ + static fdb_err_t result; + struct fdb_blob blob; + /* TSDB object */ + static struct fdb_tsdb tsdb = {0}; + /* set the lock and unlock function if you want */ + fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, (void *)fdb_lock); + fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, (void *)fdb_unlock); + /* Time series database initialization + * + * &tsdb: database object + * "log": database name + * "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table. + * Please change to YOUR partition name. + * get_time: The get current timestamp function. + * 128: maximum length of each log + * NULL: The user data if you need, now is empty. + */ + result = fdb_tsdb_init(&tsdb, "log", "TSDB", get_time, 128, NULL); + if (result != FDB_NO_ERR) + { + return FALSE; + } + + { + struct env_status status; + status.temp = 37; + status.humi = 85; + result = fdb_tsl_append(&tsdb, fdb_blob_make(&blob, &status, sizeof(status))); + status.temp = 38; + status.humi = 90; + result = fdb_tsl_append(&tsdb, fdb_blob_make(&blob, &status, sizeof(status))); + + { /* QUERY the TSDB */ + /* query all TSL in TSDB by iterator */ + fdb_tsl_iter(&tsdb, ts_query_cb, &tsdb); + } + + { /* QUERY the TSDB by time */ + /* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */ + struct tm tm_from = {.tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0}; + struct tm tm_to = {.tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0}; + time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to); + static size_t count; + /* query all TSL in TSDB by time */ + fdb_tsl_iter_by_time(&tsdb, from_time, to_time, ts_query_by_time_cb, &tsdb); + /* query all FDB_TSL_WRITE status TSL's count in TSDB by time */ + count = fdb_tsl_query_count(&tsdb, from_time, to_time, FDB_TSL_WRITE); + count = count; + __NOP(); + } + } + return TRUE; +} + +BOOL test_flashdb(void) +{ + if (test_flashdb_kv() == FALSE) + { + return FALSE; + } + if (test_flashdb_ts() == FALSE) + { + return FALSE; + } + return TRUE; // 返回TRUE +} + +/** + * @brief I2C EEPROM写入测试 + * @return {*} + */ +BOOL test_eeprom_fm24_write(void) +{ + + return TRUE; // 返回TRUE +} + +/** + * @brief I2C EEPROM读取测试 + * @return {*} + */ +BOOL test_eeprom_fm24_read(void) +{ + return TRUE; // 返回TRUE +} + +/** + * @brief 这是一个用于测试外部EEPROM的函数,它接受三个参数: + * @param {uint16_t} addr - 要写入的地址。 + * @param {uint8_t *} buf - 要写入的数据缓冲区。 + * @param {uint16_t} len - 要写入的数据长度。 + * @return {*} + * @retval TRUE - 如果写入和读回的数据相同,则返回TRUE。 + * @retval FALSE - 如果写入和读回的数据不同,则返回FALSE。 + */ +BOOL test_eeprom_fm24(void) +{ + return TRUE; // 如果所有数据都相同,返回TRUE +} + +/** + * @brief 用于检测LCD是否正常工作,并初始化LCD + * @return {*} + */ +BOOL test_lcd(void) +{ + if (HW_VER >= 003) // 如果版本号大于等于003,表示使用了V3版本 + { + // 检测到LCD低电平才初始化LCD,V3版本该引脚被使用 + if (1 == LCD_DETECT()) + { + return FALSE; // 如果检测到LCD低电平,说明LCD正常工作,返回FALSE + } + } + + gui_full(); // 填充屏幕 + gui_open(); // 打开屏幕 + + return TRUE; // LCD正常工作,返回TRUE +} + +BOOL test_led(void) +{ + uint8_t i = 0; + uint8_t ret = 0; + + for (i = 0; i < LEDS_MAX; i++) + { + leds_on((leds_e)i); + delay_tick(10); // 等待10个时钟周期 + switch (i) + { + case LEDS_1_RED: + ret = GPIO_READ(LED1_GPIO_Port, LED1_Pin); + break; + case LEDS_1_GREEN: + ret = GPIO_READ(LED2_GPIO_Port, LED2_Pin); + break; + case LEDS_1_YELLOW: + ret = GPIO_READ(LED3_GPIO_Port, LED3_Pin); + break; + case LEDS_2_ORANGE: + ret = GPIO_READ(LED4_GPIO_Port, LED4_Pin); + break; + case LEDS_2_BLUE: + ret = GPIO_READ(LED5_GPIO_Port, LED5_Pin); + break; + default: + break; + } + if (ret != 0) + { + return FALSE; // 如果读取到的状态不是1,表示设置失败 + } + } + + for (i = 0; i < LEDS_MAX; i++) + { + switch (i) + { + case LEDS_1_RED: + GPIO_SET(LED1_GPIO_Port, LED1_Pin); + delay_tick(10); + ret = GPIO_READ(LED1_GPIO_Port, LED1_Pin); + break; + case LEDS_1_GREEN: + GPIO_SET(LED2_GPIO_Port, LED2_Pin); + delay_tick(10); + ret = GPIO_READ(LED2_GPIO_Port, LED2_Pin); + break; + case LEDS_1_YELLOW: + GPIO_SET(LED3_GPIO_Port, LED3_Pin); + delay_tick(10); + ret = GPIO_READ(LED3_GPIO_Port, LED3_Pin); + break; + case LEDS_2_ORANGE: + GPIO_SET(LED4_GPIO_Port, LED4_Pin); + delay_tick(10); + ret = GPIO_READ(LED4_GPIO_Port, LED4_Pin); + break; + case LEDS_2_BLUE: + GPIO_SET(LED5_GPIO_Port, LED5_Pin); + delay_tick(10); + ret = GPIO_READ(LED5_GPIO_Port, LED5_Pin); + break; + default: + break; + } + if (ret != 1) + { + return FALSE; // 如果读取到的状态不是1,表示设置失败 + } + } + return TRUE; +} + +/** + * @brief 这是一个用于测试PWM输出的函数。 + * @brief + * @param {uint16_t} dac: 目标输出电流值 + * @return {*}: 返回一个布尔值,表示函数执行结果 + */ +BOOL test_pwm_out(float32 current) +{ + pwm_duty2current(current); + return TRUE; +} + +/** + * @brief 测试按键,通过HART测试 + * @return {*} + */ +BOOL TEST_BUTTON(void) +{ + return TRUE; +} + +/** + * @brief 用于测试hart cache,向cache添加数据 + * @return {*} + * @note + */ +hart_cache_t cache_node_test; +void hart_cache_test(void) +{ + cache_node_test.uuid = 1; + cache_node_test.hart_cache_time = 5000 + sys_millis(); + + hart_cache_add(cache_node_test); +} + +/************************** 开发板驱动自测 **************************/ +float32 temp_f; +float32 dcdc; +float32 loop_cur; +uint16_t adc[10]; +rtc_date s_date = {0x23, 0x08, 0x07, 0x01, 0x16, 0x30, 0x30}; +rtc_date r_date; +uint8_t e_data[5] = {0xD5, 0xC8, 0x00, 0x01, 0x03}; + +static void test_init(void) +{ + driver_init(); +} + +static void test_dinit(void) +{ + driver_dinit(); +} + +void bsp_test(void) +{ + test_init(); + + // 测试DCDC + DBG_ASSERT(test_dcdc(&dcdc) == TRUE __DBG_LINE); + + // 测试回路电流 + DBG_ASSERT(test_loop_current(&loop_cur) == TRUE __DBG_LINE); + + // 测试温度 + DBG_ASSERT(test_temperature(&temp_f) == TRUE __DBG_LINE); + + // 测试IP大电流输出使能 + DBG_ASSERT(test_gpio(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin) == TRUE __DBG_LINE); + + // // 测试IP输出控制 + // DBG_ASSERT(test_ip_putput_dac(3000) == TRUE __DBG_LINE); + + // 测试PWM输出 + test_pwm_out(20); + + // 测试RTC + DBG_ASSERT(test_rtc(RTC_WRITE, &s_date) == TRUE __DBG_LINE); // 设置时间 + delay_ms(2000); + DBG_ASSERT(test_rtc(RTC_READ, &r_date) == TRUE __DBG_LINE); // 读取时间 + + // // 测试SPI EEPROM + // DBG_ASSERT(test_eeprom_m95(M95_1, (_M95_SIZE - 32), e_data, 10) == TRUE __DBG_LINE); + // DBG_ASSERT(test_eeprom_m95(M95_2, (_M95_SIZE - 32), e_data, 10) == TRUE __DBG_LINE); + + // 测试flashdb 不要开放 + // DBG_ASSERT(test_flashdb() == TRUE __DBG_LINE); + + // // 测试I2C EEPROM + // DBG_ASSERT(test_eeprom_fm24() == TRUE __DBG_LINE); + // DBG_ASSERT(test_eeprom_lc02b((256 - 32), e_data, 10) == TRUE __DBG_LINE); + + // // 测试LED + // DBG_ASSERT(test_led() == TRUE __DBG_LINE); + + // 测试LCD,需要人工观察现象 + // DBG_ASSERT(test_lcd() == TRUE __DBG_LINE); + // delay_ms(2000); + + // 测试各个ADC通道 + DBG_ASSERT(test_adc(ADC_PSB_CHANNEL, &adc[1]) == TRUE __DBG_LINE); // 位置反馈 + DBG_ASSERT(test_adc(ADC_IPSB_CHANNEL, &adc[2]) == TRUE __DBG_LINE); // 小回路 + DBG_ASSERT(test_adc(ADC_BP_CHANNEL, &adc[3]) == TRUE __DBG_LINE); // 气源压力 + DBG_ASSERT(test_adc(ADC_BPA_CHANNEL, &adc[4]) == TRUE __DBG_LINE); // A路压力 + DBG_ASSERT(test_adc(ADC_BPB_CHANNEL, &adc[5]) == TRUE __DBG_LINE); // B路压力 + + test_dinit(); +} + +// NOTE: 以下函数为自测函数,不要开放,因为由fal_execution维护 +// BOOL selftest_m95_1(void) +// { +// BOOL ret; +// ret = test_eeprom_m95(M95_1, (_M95_SIZE - 32), e_data, 10); +// return ret; +// } + +// BOOL selftest_m95_2(void) +// { +// BOOL ret; +// ret = test_eeprom_m95(M95_2, (_M95_SIZE - 32), e_data, 10); +// return ret; +// } + +// BOOL selftest_fm24(void) +// { +// BOOL ret; +// ret = test_eeprom_fm24(); +// return ret; +// } + +BOOL selftest_lc02(void) +{ + BOOL ret; + ret = test_eeprom_lc02b((256 - 32), e_data, 10); + return ret; +} + +/** + * @brief 功耗测试 + * @return {*} + * @note + */ +static void power_test_open_pressure(void) +{ + BP_A_POWER_ON(); + BP_B_POWER_ON(); + // BP_S_POWER_ON(); +} + +static void power_test_open_led(void) +{ + leds_on(LEDS_1_GREEN); + // leds_on(LEDS_1_RED); + // leds_on(LEDS_2_ORANGE); + // leds_on(LEDS_2_BLUE); + // leds_on(LEDS_1_YELLOW); +} +static void power_test_output_swo(void) +{ + SWO1_OPEN(); + // SWO2_OPEN(); +} + +static void power_test_output_pwm(uint16_t current) +{ + test_pwm_out(current); +} + +void power_test(void) +{ + // 初始化 + test_init(); + // 使能压力传感器 + power_test_open_pressure(); + // 使能LED + power_test_open_led(); + // 使能SWO + power_test_output_swo(); + // 使能PWM + power_test_output_pwm(20); +} diff --git a/Tests/test_bsp.h b/Tests/test_bsp.h new file mode 100644 index 0000000..5ab5a65 --- /dev/null +++ b/Tests/test_bsp.h @@ -0,0 +1,59 @@ +#ifndef __TEST_BSP_H__ +#define __TEST_BSP_H__ +#include "test.h" +#include "rtc_rx8010.h" +#include "lib.h" +#include "entity.h" +#include "board.h" +#include "rtc_rx8010.h" +#include "eeprom_m95.h" +#include "eeprom_fm24.h" +#include + +typedef enum +{ + RTC_WRITE = 0, + RTC_READ = 1, +} rtc_opt_e; + +// RTC测试程序 +BOOL test_rtc(uint8_t opt, rtc_date *data); +// 测试回路电流 +BOOL test_loop_current(float32 *cur); +// 测试ADC通道 +BOOL test_adc(uint8_t chan, uint16_t *adc); +// 测试温度 +BOOL test_temperature(float32 *temp_f); +// DAC测试IP输出控制 +BOOL test_ip_putput_dac(uint16_t value); +// PWM测试IP输出控制 +BOOL test_ip_putput_pwm(float32 duty_percent); +// 测试DCDC电压 +BOOL test_dcdc(float32 *vol); +// 测试GPIO +BOOL test_gpio(GPIO_TypeDef *port, uint16_t pin); +// 测试PWM输出控制 +BOOL test_pwm_out(float32 current); +// 测试LCD +BOOL test_lcd(void); +// 测试M95-写 +BOOL test_eeprom_m95_write(m95_number_e num, uint8_t *buf, uint16_t len); +// 测试M95-读 +BOOL test_eeprom_m95_read(m95_number_e num, uint8_t *buf, uint16_t len); +// 测试FM24-写 +BOOL test_eeprom_fm24_write(void); +// 测试FM24-读 +BOOL test_eeprom_fm24_read(void); +// 测试按键,通过HART测试 +BOOL TEST_BUTTON(void); +// hart cache测试 +void hart_cache_test(void); +// 自检 +BOOL selftest_lc02(void); + +// 驱动测试 +void bsp_test(void); +// 功耗测试 +void power_test(void); + +#endif // __TEST_BSP_H__ diff --git a/Tests/test_hart.c b/Tests/test_hart.c new file mode 100644 index 0000000..b363abc --- /dev/null +++ b/Tests/test_hart.c @@ -0,0 +1,43 @@ +#include +#include + +#define NUM_TO_ASCII(num) ((num) + '0') + +void dev_serial_number_to_string(char *s, uint8_t *sn, uint8_t len) +{ + uint8_t interval = 0; // 间隔x位插入'-' + uint8_t count = 0; + for (uint8_t i = 0; i < len; i++) + { + s[count] = NUM_TO_ASCII(*(sn + i)); + count++; + if (interval != 0) + { + if ((i + 1) % interval == 0 && count < count + len / interval) + { + s[count] = '-'; + count++; + } + } + } + + if (interval != 0) + { + s[len + len / interval - 1] = '\0'; // 添加字符串结束符 + } + else + { + s[len] = '\0'; // 添加字符串结束符 + } +} + +int main() +{ + uint8_t sn[16] = {0}; // 16个0 + char s[19]; // 16 digits + 3 dashes + 1 null terminator + dev_serial_number_to_string(s, sn, 16); + + printf("Formatted serial number: %s\n", s); + + return 0; +} diff --git a/User/app.c b/User/app.c new file mode 100644 index 0000000..a303559 --- /dev/null +++ b/User/app.c @@ -0,0 +1,136 @@ +/** + * @file app.c + * @author xxx + * @date 2023-08-30 08:58:43 + * @brief app初始化和app启动 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "app.h" +#include "adcs.h" +#include "test_bsp.h" +#include "bootload.h" + +__IO calib_param_t calib_param[CALIBPARA_NUM]; // 校准参数 +device_typedef udevice; // 设备参数 +real_time_data_t rt_data; // 实时参数 +pid_t _pid; // pid参数 +driver_icon_enable_u driver_icon_enable; // 驱动使能图标 +uint32_t mode_default_autoload; // 默认自动加载 +// 模拟量 +__IO uint16_t adc_raw[ADC1_MAX]; // ADC原始值 +// 数字量 +__IO float32 pid_target = 0; // pid控制目标 +__IO float32 pid_actual = 0; // pid控制实际 +__IO float32 show_loop = 0; // 显示电流 +__IO float32 show_target = 0; // 显示目标 +__IO float32 show_actual = 0; // 显示实际 +__IO float32 range_percentage; // 量程百分比 +__IO const static uint32_t cupid_encrypt = 0xFFFFFFFF; +#ifndef BOOTLOAD // 非bootload模式 +static void app_preload(void) +{ + mode_default_autoload = LL_TIM_GetAutoReload(TIM7); + + if (app_preload_flag != 0xa5) + { + app_preload_flag = 0xa5; + udevice.display_language = CHINESE; + app_preload_language_flag = udevice.display_language; + app_preload_cupid_encrypt = 0xFFFFFFFF; + } + else + { + udevice.display_language = app_preload_language_flag; + } + + set_app_preload_bootload_flag(FALSE); +} +/** + * @brief BOOTLOAD传输数据 + * @param {uint8_t} *data + * @param {uint16_t} len + * @return {*} + * @note + */ +static void bootload_transmit(const uint8_t data_src, const uint8_t *data, const uint16_t len) +{ + extern uart_t *uarts[APP_UART_MAX]; + uart_send_data(uarts[data_src], (uint8_t *)data, len); +} + +/** + * @brief BOOTLOAD更新完成处理 + * @return {*} + * @note BOOTLOAD更新完成恢复业务流程,这个时候不要重启 + */ +static void bootload_end(BOOL bootload_write_flag) +{ + set_app_preload_bootload_flag(FALSE); // 更新完成恢复业务流程 + if (bootload_write_flag == TRUE) + { + set_app_preload_bootload_jump_flag(APP_PRELOAD_BOOTLOAD_JUMP_WAIT); // 更新完成等待用户通知跳转到bootload + } + else + { + set_app_preload_bootload_jump_flag(APP_PRELOAD_BOOTLOAD_JUMP_NONE); + // 更新失败 通知用户 + } +} +#endif + +/** + * @brief app初始化 + * @return {*} + * @note + */ +void app_init(void) +{ + leds_on_all(); // 打开所有LED +#ifndef BOOTLOAD // 非bootload模式 + app_preload(); // 预加载 + { + system_clock_config_set_flag(TRUE); + system_clock_config_hight(); // 切换高频 + fal_execution_init(); // fal初始化 + params_init(); // 参数初始化 + system_clock_config_low(); // 切换低频 + app_hart_init(); // HART初始化 + mode_init(); // 工作模式初始化 + flow_init(); // 流程初始化 + + bootload_init(bootload_transmit, bootload_end); // 在用户代码中接受更新文件需要初始化bootload + } + + // TIM6 is placed after app_init to wait for the completion of fal_execution initialization. + ENABLE_TIM(TIM6); // Enable TIM6 +#if LCD_DESIGN == TRUE + ENABLE_TIM(TIM7); // Enable TIM7 +#endif + +#else // bootload模式 + // 在BOOTLOAD模式下需要关闭所有外设,且不需要接受用户代码,所以不需要初始化 + board_dinit(); +#endif + + leds_off_all(); // 关闭所有LED +} + +/** + * @brief app反初始化 + * @return {*} + * @note + */ +void app_dinit(void) +{ +} + +/** + * @brief 业务流程启动 + * @return {*} + * @note + */ +void app_start(void) +{ + flow_start(); +} diff --git a/User/app.h b/User/app.h new file mode 100644 index 0000000..791c907 --- /dev/null +++ b/User/app.h @@ -0,0 +1,86 @@ +/** + * @file app.h + * @author: xxx + * @date: 2023-06-29 13:21:02 + * @brief 应用层 + * @copyright: Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#ifndef __APP_H__ +#define __APP_H__ +#include "main.h" +#include "board.h" +#include "delay.h" +#include "pid.h" + +#include "entity.h" + +#include "fal_execution.h" // fal +#include "key.h" // 按键 +#include "params.h" // 参数 +#include "convert.h" // 转换 +#include "diagnosis.h" // 诊断 +#include "mode.h" // 工作模式 + +typedef enum +{ + APP_UART_1, + APP_UART_2, + APP_UART_MAX, +} app_uart_e; + +// 这里的结构体不能使用1字节对齐,让其自动对齐 +typedef struct +{ + float32 input_current; // 输入电流 + uint16_t valve_feedback; // 阀位反馈 + uint16_t atmospheric_pressure_source; // 气压源压力 + uint16_t pressure_at_port_a; // A口压力 + uint16_t pressure_at_port_b; // B口压力 + uint16_t amplifier_circuit; // 放大器回路 + float32 built_in_temperature; // 内置温度 + uint16_t ip_output_detection; // IP输出检测 + float32 valve_percentage; // 阀位百分比 +} app_analog_quantity_t; // 模拟量 + +typedef struct +{ + float32 input_current; // 输入电流 + uint16_t valve_feedback; // 阀位反馈 + uint16_t atmospheric_pressure_source; // 气压源压力 + uint16_t pressure_at_port_a; // A口压力 + uint16_t pressure_at_port_b; // B口压力 + uint16_t amplifier_circuit; // 放大器回路 + float32 built_in_temperature; // 内置温度 + uint16_t ip_output_detection; // IP输出检测 + + float32 target_row; // 目标行程 + float32 current_row; // 当前行程 + float32 friction; // 摩擦力 + float32 spring_force; // 弹簧力 +} app_digital_quantity_t; // 数字量 + +typedef struct +{ + app_analog_quantity_t analog_quantity; + app_digital_quantity_t digital_quantity; +} app_dynamics_t; + +extern void app_init(void); +extern void app_dinit(void); +extern void app_start(void); + +extern void flow_init(void); +extern void flow_start(void); +extern void bootload_flow_start(void); + +extern BOOL app_hart_init(void); +extern void app_hart_inspection(void); +extern BOOL app_hart_is_idle(void); +extern void hart_uart_init(void); +extern void hart_uart_dinit(void); +extern void hart_ble_init(void); +extern void hart_ble_dinit(void); +extern void hart_rx_process(void); +extern void h24_bluetooth_work(uint8_t index); +extern void menu_inspection(void); +#endif // __APP_H__ diff --git a/User/app_flow.c b/User/app_flow.c new file mode 100644 index 0000000..fc6f34b --- /dev/null +++ b/User/app_flow.c @@ -0,0 +1,386 @@ +/** + * @file app_flow.c + * @author xxx + * @date 2023-08-30 08:58:43 + * @brief 此文件用于管理各个任务流程 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include +#include "app.h" +#include "main.h" +#include "flow.h" +#include "tim.h" +#include "filter.h" + +#include "mode.h" +#include "at_hc24.h" +#include "bootload.h" + +__IO flow_event_e flow_event = FLOW_EVENT_NORMAL; // 流程事件 + +static struct flow business_fw; // 业务流程 +static struct flow system_fw; // 系统检测 +static struct flow btn_fw; // 按键检测 +static struct flow idle_fw; // 空闲任务 +// bootloader +static struct flow bootload_system_fw; // BOOTLOAD系统流程 +// 子任务 +static struct flow current_fw; // 电流检测 + +uint16_t scheduler_use_time = 0; + +/** + * @brief 菜单检测 + * @return {*} + * @note + */ +void menu_inspection(void) +{ + +} + +/** + * @brief 图标检测 + * @return {*} + * @note + */ +static void icon_inspection(void) +{ + if (FALSE == HART_IS_ENABLE()) + { + driver_icon_enable.Bits.hart = 0; // 禁用HART + } + else + { + driver_icon_enable.Bits.hart = 1; // 使能HART + } + + if (FALSE == BLE_IS_ENABLE()) // 检查蓝牙是否已启用 + { + driver_icon_enable.Bits.bluetooth = 0; // 禁用蓝牙 + } + else + { + driver_icon_enable.Bits.bluetooth = 1; // 使能蓝牙 + } + + driver_icon_enable.Bits.work_mode = (uint8_t)udevice.dev_work_mode; // 工作模式 + + // TODO 设备是否锁定检查 +} + +static void bootload_start_inspection(void) +{ +} + +/** + * @brief 温度检测任务 + * @return {*} + * @note 该函数用于检测当前温度并执行相应的任务: + * 1. LCD的开启和关闭 + */ +static void temperature_inspection(void) +{ + // 定义一个布尔变量lcd_close,用于标记LCD是否已关闭 + static BOOL lcd_close = FALSE; + // 获取当前温度 + rt_data.temperature = get_temperature(); + // 判断温度是否大于等于LCD工作温度最小值,如果是,则启动LCD + if (rt_data.temperature >= LCD_WORK_TEMP_MIN) + { + lcd_init(); // 初始化LCD + if (lcd_close == TRUE) // 检查LCD是否已关闭,如果是,则打开LCD + { + lcd_close = FALSE; + } + + gui_set_scandir(udevice.display_direction); // 更新扫描方向 + gui_open(); // 打开LCD + } + // 否则,关闭LCD + else + { + lcd_dinit(); + lcd_close = TRUE; + } +} + +/************************************************ 以下为应用线程 ************************************************/ + +/** + * @brief 电流检测任务(子任务) + * @return {*} + * @note 该函数用于检测当前电量并执行相应的任务: + * 1. HART的启动和关闭 + * 2. 蓝牙的启动和关闭 + */ +static uint8_t current_inspection(struct flow *fl) +{ + FL_HEAD(fl); + // 定义一个浮点数变量loop_current,用于存储当前电流 + static float32 current = 0.0; + // 计算当前电流,方法为读取ADC通道ADC_LOOP_CHANNEL的平均值并转换为浮点数 + current = loop_current_convert(adc_result_average(ADCS_1, ADC_LOOP_CHANNEL)); + + // 判断当前电流是否大于等于3.8mA,如果是,则启动UART + if (current >= INPUT_CURRENT_MIN) + { + driver_init(); // 初始化驱动 + if (FALSE == HART_IS_ENABLE()) // 检查HART是否已启用,如果否,则初始化HART UART + { + hart_uart_init(); + } + } + // 否则,关闭UART + else + { + driver_dinit(); // 关闭驱动 + hart_uart_dinit(); // 关闭HART UART + } + + // 判断当前电流是否大于等于xx mA且工作模式在离线模式下,如果是,则启动蓝牙 + if ((current >= BLE_CURRENT_WORK && udevice.dev_work_mode == OFF_LINE_MODE) || + (current >= BLE_CURRENT_WORK && H24_BLE_OUTPUT_DBG == TRUE)) + { + if (FALSE == BLE_IS_ENABLE()) // 检查蓝牙是否已启用,如果否,则初始化蓝牙 + { + hart_ble_init(); + } + else + { + // 检查蓝牙是否正常工作 + if (BIT_IS_CLR(hc_24_state, BIT2)) + { + h24_bluetooth_work(1); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + if (BIT_IS_SET(hc_24_state, BIT0)) + { + // 检查蓝牙名称 + h24_bluetooth_work(2); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + if (BIT_IS_CLR(hc_24_state, BIT1)) + { + // 设置蓝牙名称 + h24_bluetooth_work(3); + } + BIT_SET(hc_24_state, BIT2); + } + else + { + BIT_SET(hc_24_state, BIT2); // 如果蓝牙被主动连接的话,上面的AT指令不会有响应 + } + } + else + { + // h24_bluetooth_work(100); + } + } + } + // 否则,关闭蓝牙 + else + { + } + FL_TAIL(fl); +} + +/** + * @brief 按键检测任务 + * @return {*} + */ +static uint8_t btn_inspection(struct flow *fl) +{ + FL_HEAD(fl); + for (;;) + { + scheduler_time_start(); + // 按键检测和处理 + button_ticks(); + scheduler_use_time = scheduler_time_stop(); + FL_LOCK_DELAY(fl, FL_CLOCK_10MSEC); + } + FL_TAIL(fl); +} + +/** + * @brief 系统检测 + * @param {struct flow *} fl + * @return {*} + */ +static uint8_t systom_inspection(struct flow *fl) +{ + FL_HEAD(fl); + static BOOL run_first = TRUE; + for (;;) + { + scheduler_time_start(); + // 当前电流检测 + current_inspection(¤t_fw); + // 温度检测 + temperature_inspection(); + scheduler_use_time = scheduler_time_stop(); + // 图标检测 + icon_inspection(); + scheduler_use_time = scheduler_time_stop(); + if (run_first == TRUE) + { + run_first = FALSE; + +#if LCD_DESIGN == FALSE + ENABLE_TIM(TIM7); // TIM7用于算法控制 +#endif + } + else + { + scheduler_use_time = scheduler_time_stop(); + + fal_execution_inspection(1000); + scheduler_use_time = scheduler_time_stop(); + + set_app_preload_language_flag(udevice.display_language); + + scheduler_use_time = scheduler_time_stop(); + } + + scheduler_use_time = scheduler_time_stop(); + + bootload_start_inspection(); + + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + } + FL_TAIL(fl); +} + +/** + * @brief 业务流程 + * @param {flow} *fl + * @return {*} + */ +static uint8_t business_inspection(struct flow *fl) +{ + FL_HEAD(fl); + for (;;) + { + scheduler_time_start(); + // 工作模式检测 + mode_detection(); + + scheduler_use_time = scheduler_time_stop(); + FL_LOCK_DELAY(fl, FL_CLOCK_100MSEC); + } + FL_TAIL(fl); +} + +/** + * @brief 空闲任务用来计算CPU占用率和内存使用率 + * @param {flow} *fl + * @return {*} + * @note + */ +static uint8_t idle_inspection(struct flow *fl) +{ + FL_HEAD(fl); + for (;;) + { + rt_data.cpu_percent = scheduler_time_occupancy_get(1000); + rt_data.cpu_temperature = adc_result_temperature(adc_result_average(ADCS_1, ADC_TEMP_CHANNEL)); + rt_data.mem_percent = my_mem_perused(SRAMIN); + leds_toggle(LEDS_2_BLUE); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + } + FL_TAIL(fl); +} + +/** + * @brief bootload系统检测 + * @param {struct flow *} fl + * @return {*} + */ +static uint8_t bootload_systom_inspection(struct flow *fl) +{ + FL_HEAD(fl); + for (;;) + { + // 电流检测 + current_inspection(¤t_fw); + + if (TRUE == BLE_IS_ENABLE()) + { + leds_off(LEDS_1_RED); + leds_toggle(LEDS_1_GREEN); + } + else + { + leds_off(LEDS_1_GREEN); + leds_toggle(LEDS_1_RED); + } + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + } + FL_TAIL(fl); +} + +/** + * @brief: 流程启动 + * @return {*} + */ +void flow_start(void) +{ + if (TRUE == app_hart_is_idle()) + { + switch (flow_event) + { + case FLOW_EVENT_NORMAL: + { + systom_inspection(&system_fw); // 系统检测 + business_inspection(&business_fw); // 业务流程检测 + btn_inspection(&btn_fw); // 按键检测 + idle_inspection(&idle_fw); // 空闲任务用来计算CPU占用率 + break; + } + case FLOW_EVENT_DIAGNOSIS: + { + systom_inspection(&system_fw); // 系统检测 + current_inspection(¤t_fw); // 当前电流检测 + break; + } + default: + break; + } + + hart_rx_process(); // HART接收处理 + } +} + +/** + * @brief: bootload流程启动 + * @return {*} + */ +void bootload_flow_start(void) +{ + bootload_systom_inspection(&bootload_system_fw); // BOOTLOAD系统流程 + if (BIT_IS_CLR(hc_24_state, BIT2) == FALSE) + { + bootload_inspection(); // BOOTLOAD检测 + if (bootload_timeout() == TRUE) + { + // 如果超时退出bootload模式 + set_app_preload_bootload_flag(FALSE); + leds_off_all(); + } + } +} + +/** + * @brief 初始化流程 + * @return {*} + */ +void flow_init(void) +{ + FL_INIT(¤t_fw); // 电流检测 + FL_INIT(&system_fw); // 系统检测 + FL_INIT(&business_fw); // 业务流程 + FL_INIT(&btn_fw); // 按键检测 + FL_INIT(&idle_fw); // 空闲任务 + FL_INIT(&bootload_system_fw); // bootload系统流程 + FL_INIT(¤t_fw); // 电流检测 +} diff --git a/User/app_hart.c b/User/app_hart.c new file mode 100644 index 0000000..6550bb7 --- /dev/null +++ b/User/app_hart.c @@ -0,0 +1,317 @@ +/** + * @file app_hart.c + * @author xxx + * @date 2023-07-06 13:08:52 + * @brief 此文件主要实现板卡的HART功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "app.h" +#include "uarts.h" +#include "test_bsp.h" +#include "at_hc24.h" +#include "bootload.h" +#include "ymodem.h" +#include "flow.h" + +#define HART_UART1 USART1 +#define HART_UART2 UART5 + +#define HART_UART_RXSIZE (240u) +#define BLE_UART_RXSIZE (1100u) // 接收1100个字节,考虑到BOOTLOAD需要接收大量数据,在RAM允许的情况下,可以适当增大 +#define HART_UART_TXSIZE (240u) // 发送240个字节 + +uart_t *uarts[APP_UART_MAX]; + +static struct flow hart_handle_fw; // HART处理流程 +static struct flow_sem hart_msg_sem; // 消息信号量,用于同步 + int8_t hart_msg_uart_index; // 消息来源的串口索引,会有并发问题,不能蓝牙和HART同时来数据 +static uint8_t hart_recv_msg[HART_UART_RXSIZE]; // HART接收数据缓存 +static uint16_t hart_recv_msg_len; // HART接收数据长度 + +app_dynamics_t app_dynamics; +static __IO BOOL hart_idle = TRUE; + +/** + * @brief 蓝牙输出 + * @param {uint8_t} *data + * @param {uint16_t} len + * @return {*} + * @note + */ +void h24_bluetooth_output(uint8_t *data, uint16_t len) +{ + DBG_ASSERT(data != NULL __DBG_LINE); + if (len == 0) + { + return; + } + else + { + if (uarts[APP_UART_2] != NULL) + { + uart_send_data(uarts[APP_UART_2], data, len); + } + } +} + +void h24_bluetooth_output_dbg(uint8_t *data, uint16_t len) +{ + DBG_ASSERT(data != NULL __DBG_LINE); + if (len == 0) + { + return; + } + else + { +#if H24_BLE_OUTPUT_DBG == TRUE + if (BIT_IS_SET(hc_24_state, BIT2)) + { + h24_bluetooth_output(data, len); + } +#endif + } +} + +/** + * @brief 蓝牙H24模块配置工作 + * @return {*} + * @note + */ +void h24_bluetooth_work(uint8_t index) +{ + uint8_t len = 0; + char data[128]; + osel_memset((uint8_t *)data, 0, 128); +#ifdef V4 + char device_id[] = "LP4-???"; +#elif V5 + char device_id[] = "LP5-???"; +#elif BOOTLOAD + char device_id[] = "BOOTLOAD"; +#else + char device_id[] = "LP3-???"; +#endif + char *test_cmd[AT_END] = { + "AT", + "AT+NAME", + "AT+NAME=%s", + "AT+RESET", + }; + switch (index) + { + case 1: // 测试指令 + { + hc_24_state = 0; + sprintf(data, test_cmd[AT_CMD_TEST]); + len = osel_mstrlen((unsigned char *)data); + h24_bluetooth_output((uint8_t *)data, len); + break; + } + + case 2: // 获取设备名称 + { + at_set_memcmp_cache((unsigned char *)device_id, osel_mstrlen((unsigned char *)device_id)); + sprintf(data, test_cmd[AT_CMD_NAME_REQ]); + len = osel_mstrlen((unsigned char *)data); + h24_bluetooth_output((uint8_t *)data, len); + break; + } + + case 3: // 设置设备名称 + { + at_set_memcmp_cache((unsigned char *)device_id, osel_mstrlen((unsigned char *)device_id)); + sprintf(data, test_cmd[AT_CMD_NAME], device_id); + len = osel_mstrlen((unsigned char *)data); + h24_bluetooth_output((uint8_t *)data, len); + break; + } + case 4: // 复位 + { + hc_24_state = 0; + sprintf(data, test_cmd[AT_CMD_DISA]); + len = osel_mstrlen((unsigned char *)data); + h24_bluetooth_output((uint8_t *)data, len); + break; + } + case 100: + { + sprintf(data, "%f,%f,%f\r\n", 1.1, 2.2, 3.3); + len = osel_mstrlen((unsigned char *)data); + h24_bluetooth_output((uint8_t *)data, len); + break; + } + default: + break; + } +} + +// HART处理流程 +static uint8_t hart_handle_inspection(struct flow *fl) +{ + FL_HEAD(fl); + for (;;) + { + FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &hart_msg_sem, FL_CLOCK_SEC * 3600); + if (FL_SEM_IS_RELEASE(fl, &hart_msg_sem) && hart_recv_msg_len != 0) + { + // hart_handle(hart_msg_uart_index, hart_recv_msg, hart_recv_msg_len); + hart_recv_msg_len = 0; + } + } + FL_TAIL(fl); +} + +// HART接收处理 +void hart_rx_process(void) +{ + hart_handle_inspection(&hart_handle_fw); +} + +// 串口1、5接收中断回调函数 +static void hart_rx_cb(uint8_t uart_index, uint8_t *data, uint16_t len) +{ + DBG_ASSERT(uart_index < APP_UART_MAX __DBG_LINE); + hart_idle = FALSE; + + if (data[0] == 'O' && data[1] == 'K') // 蓝牙协议 + { + data[0] = 'A'; + data[1] = 'T'; + at_cmd_parse(data, len); + } + else if (data[0] == 'B' && data[1] == 'T') // 收到BOOTLOAD启动命令 + { + if (osel_memcmp(data, "BT RUN", 6) == 0) + { + if (get_app_preload_bootload_flag() == FALSE) // 如果已经在BOOTLOAD模式下,不再重复启动 + { + set_app_preload_bootload_flag(TRUE); // 设置BOOTLOAD标志 + bootload_transmit_from(uart_index); // 从指定位置开始发送数据 + } + } + else if (osel_memcmp(data, "BT STOP", 7) == 0) + { + set_app_preload_bootload_flag(FALSE); // 设置BOOTLOAD标志 + } + } + else + { + // 注:在BOOTLOAD模式下,不接收HART数据 +#ifndef BOOTLOAD + // 通过消息的方式存在蓝牙和HART模块并发冲突,实际情况不会发生,HART协议传输速度慢,存储的数据可以使用全局的方式 + hart_msg_uart_index = uart_index; + osel_memcpy(hart_recv_msg, data, len); + hart_recv_msg_len = len; + FLOW_SEM_RELEASE(&hart_msg_sem); +#else + rym_receive(uart_index, data, len); +#endif + } + hart_idle = TRUE; +} + +static void hart_tx_complete_cb(void) +{ + // 串口1发送完成回调函数 + HART_RTS_ON(); +} + +// HART协议的使用的串口 --- 串口1 +void hart_uart_init(void) +{ + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1); + GPIO_SET_OUTPUT(HART_PWR_GPIO_Port, HART_PWR_Pin); + GPIO_SET_OUTPUT(HART_RST_GPIO_Port, HART_RST_Pin); + GPIO_SET_OUTPUT(HART_RTS_GPIO_Port, HART_RTS_Pin); + GPIO_SET_ALTERNATE(HART_TX_GPIO_Port, HART_TX_Pin); + GPIO_SET_ALTERNATE(HART_RX_GPIO_Port, HART_RX_Pin); + LL_mDelay(10); + // 串口1初始化开始 + HART_RTS_ON(); + HART_RST_OFF(); + LL_mDelay(20); + HART_RST_ON(); + HART_EN_DISABLE(); + HART_EN_ENABLE(); + HART_RTS_ON(); + if (uarts[APP_UART_1] == NULL) + { + LL_mDelay(100); + uarts[APP_UART_1] = uart_create(HART_UART1, TRUE, HART_UART_RXSIZE, hart_rx_cb, TRUE, HART_UART_TXSIZE, hart_tx_complete_cb); + uarts[APP_UART_1]->uart_index = APP_UART_1; + uarts[APP_UART_1]->dma = DMA2; + uarts[APP_UART_1]->dma_rx_channel = LL_DMA_CHANNEL_7; + uarts[APP_UART_1]->dma_tx_channel = LL_DMA_CHANNEL_6; + uart_recv_en(uarts[APP_UART_1]); + } + // 串口1初始化结束 +} + +// HART协议使用的串口,为模拟IO口 +void hart_uart_dinit(void) +{ + HART_EN_DISABLE(); + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_USART1); + LL_USART_Disable(USART1); + GPIO_SET_ANALOG(HART_PWR_GPIO_Port, HART_PWR_Pin); + GPIO_SET_ANALOG(HART_RST_GPIO_Port, HART_RST_Pin); + GPIO_SET_ANALOG(HART_CD_GPIO_Port, HART_CD_Pin); + GPIO_SET_ANALOG(HART_TX_GPIO_Port, HART_TX_Pin); + GPIO_SET_ANALOG(HART_RX_GPIO_Port, HART_RX_Pin); +} + +// 蓝牙模块串口初始化 +void hart_ble_init(void) +{ + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART5); + GPIO_SET_OUTPUT(BLE_PWR_GPIO_Port, BLE_PWR_Pin); + GPIO_SET_INPUT(BLE_RST_GPIO_Port, BLE_RST_Pin); + GPIO_SET_ALTERNATE(BLE_TX_GPIO_Port, BLE_TX_Pin); + GPIO_SET_ALTERNATE(BLE_RX_GPIO_Port, BLE_RX_Pin); + BLE_EN_ENABLE(); + if (uarts[APP_UART_2] == NULL) + { + LL_mDelay(100); + uarts[APP_UART_2] = uart_create(HART_UART2, TRUE, BLE_UART_RXSIZE, hart_rx_cb, TRUE, HART_UART_TXSIZE, NULL); + uarts[APP_UART_2]->uart_index = APP_UART_2; + uarts[APP_UART_2]->dma = DMA2; + uarts[APP_UART_2]->dma_rx_channel = LL_DMA_CHANNEL_2; + uarts[APP_UART_2]->dma_tx_channel = LL_DMA_CHANNEL_1; + uart_recv_en(uarts[APP_UART_2]); + } +} + +// 蓝牙模块端口IO口反初始化 +void hart_ble_dinit(void) +{ + // 关闭蓝牙串口 + BLE_EN_DISABLE(); + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_UART5); + LL_USART_Disable(UART5); + // 端口转成模拟IO口 + GPIO_SET_ANALOG(BLE_PWR_GPIO_Port, BLE_PWR_Pin); + GPIO_SET_ANALOG(BLE_RST_GPIO_Port, BLE_RST_Pin); + GPIO_SET_ANALOG(BLE_TX_GPIO_Port, BLE_TX_Pin); + GPIO_SET_ANALOG(BLE_RX_GPIO_Port, BLE_RX_Pin); +} + +// 判断是否闲置的结果 +BOOL app_hart_is_idle(void) +{ + return hart_idle; +} + +// HART初始化 +BOOL app_hart_init(void) +{ + uarts[APP_UART_1] = NULL; + uarts[APP_UART_2] = NULL; + FL_INIT(&hart_handle_fw); // 系统检测 + // 判断当前电流 >=8mA启动蓝牙 >=3.8mA启动uart + // 注:串口初始化移动到all_flow + // hart_uart_init(); + // hart_ble_init(); + return TRUE; +} + diff --git a/User/app_hart.h b/User/app_hart.h new file mode 100644 index 0000000..9317f13 --- /dev/null +++ b/User/app_hart.h @@ -0,0 +1,16 @@ +#ifndef __APP_HART_H__ +#define __APP_HART_H__ +#include "lib.h" + +typedef enum +{ + HART_FILE_MODE_DIAGNOSIS = 3, // 模式诊断 +} hart_file_read_e; + +typedef enum +{ + HART_TUNING_STOP = 1, // 退出 + HART_TUNING_START = 3, // 开始 +} hart_tuning_e; + +#endif // __APP_HART_H__ diff --git a/User/application/inc/at_hc24.h b/User/application/inc/at_hc24.h new file mode 100644 index 0000000..efe87bc --- /dev/null +++ b/User/application/inc/at_hc24.h @@ -0,0 +1,51 @@ +#ifndef __ATHC24_H__ +#define __ATHC24_H__ +#include "stdio.h" +#include "string.h" +#include "data_type_def.h" +#include "osel_arch.h" + +#define AT_SUCCESS (0) /* 指令正常 */ +#define AT_ERR (1) /* 指令异常 */ +#define AT_ERR_UNINVAIL (2) /* 没有对应指令 */ +#define AT_ERR_FUN_UNUSED (3) /* 没有可执行函数 */ + +#define ROBOT_DEBUG + +#ifdef ROBOT_DEBUG +#define AT_DEBUG_INFO(format, ...) printf(format, ##__VA_ARGS__) +#else +#define AT_DEBUG_INFO(format, ...) +#endif + +typedef unsigned char (*pFunc)(unsigned char *ptr, unsigned char len); + +typedef enum +{ + AT_CMD_TEST = 0, /* 测试指令 */ + AT_CMD_NAME_REQ, /* 查询名称 */ + AT_CMD_NAME, /* 设置名称 */ + AT_CMD_DISA, /* 断开当前连接 */ + AT_CMD_TX_POWER, /* 设置发送功率 */ + AT_CMD_ADV_INTERVAL, /* 设置广播间隔 */ + AT_CMD_CON_INTERVAL, /* 设置连接间隔 */ + AT_CMD_ADV_ONOFF, /* 设置打开、关闭广播 */ + AT_GET_VER, /* 获取版本号 */ + AT_GET_CON_STATE, /* 获取连接状态 */ + AT_CMD_UART_CFG, /* 配置UART参数 */ + AT_END +} at_cmd_e; + +typedef struct +{ + at_cmd_e cmd; /* 指令序号 */ + char *str; /* 指令内容 */ + pFunc cb; /* 指令执行 */ +} at_cmd_func_t; + +/* 返回值参数内容如上, p-指向解析的指令,len-解析指令长度 */ +unsigned char at_cmd_parse(unsigned char *p, unsigned char len); +void at_set_memcmp_cache(unsigned char *p, unsigned char len); +extern unsigned char hc_24_state; + +#endif // __ATHC24_H__ diff --git a/User/application/inc/convert.h b/User/application/inc/convert.h new file mode 100644 index 0000000..903586a --- /dev/null +++ b/User/application/inc/convert.h @@ -0,0 +1,32 @@ +/** + * @file convert.h + * @author xxx + * @date 2023-08-29 07:58:27 + * @brief 头文件 convert.h + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __CONVERT_H__ +#define __CONVERT_H__ +#include "lib.h" +#include "main.h" +#include "entity.h" + +extern void dev_serial_number_to_string(char *s, uint8_t *sn, uint8_t len, uint8_t interval, char *fix); // 16进制转ASCII字符串 +extern void hart_long_address_to_string(char *s, uint8_t *sn, uint8_t len); // HART长地址转字符串 +extern float32 i2psb(float32 in); // 输入电流转换成需要控制的阀门开度 +extern float32 temperature_c2f(float32 celsius); // 温度值转换:摄氏度转华氏度 +extern float32 pressure_kpa2unit(float32 kpa, uint16_t unit); // 压力值转换 + +extern float32 small_signal_deal(float32 in); // 小信号切除处理 +extern float32 dead_zone_deal(float32 in); // 死区处理 +extern float32 part_travel_deal(float32 in); // 分程处理 +extern void pwm_output_deal(float32 in); // PWM输出处理 +extern void swo_output_deal(float32 in); // SWO输出处理 +extern float32 target_travel_deal(float32 in); // 目标行程处理 +extern float32 actual_travel_deal(float32 in); // 实际行程处理 +extern float32 get_show_travel(float32 in); // 获取显示行程 +extern float32 get_pid_travel(float32 in); // 获取PID控制行程 +extern void get_pressure_unit(char *s, uint16_t unit); // 获取压力单位 +extern float32 pressure_adc_to_percent(uint16_t psi_adc); // 压力转百分比 +#endif // __CONVERT_H__ diff --git a/User/application/inc/diagnosis.h b/User/application/inc/diagnosis.h new file mode 100644 index 0000000..010a3ae --- /dev/null +++ b/User/application/inc/diagnosis.h @@ -0,0 +1,126 @@ +/** + * @file diagnosis.h + * @author xxx + * @date 2023-09-05 09:18:39 + * @brief 定位器诊断模块 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#ifndef __DIAGNOSIS_H__ +#define __DIAGNOSIS_H__ +#include "lib.h" +#include "entity.h" + +// 诊断等级 +typedef enum +{ + DIAGNOSIS_CLASS_FAIL = 0, // 设备故障 + DIAGNOSIS_CLASS_SPEC, // 超出规格 + DIAGNOSIS_CLASS_CHECK, // 功能检查 + DIAGNOSIS_CLASS_MAINT, // 请求维护 + DIAGNOSIS_CLASS_OK, // 诊断正常 +} diag_class_e; + +#define DIAG_FAULT_CLASS_NUM DIAGNOSIS_CLASS_OK + +// 设备故障诊断 +typedef enum +{ + DIAGNOSIS_VREF = 0, ///< 基准电压诊断 => 供电系统故障 + DIAGNOSIS_INPUT_UPPER, ///< 输入电流上限诊断 => 驱动电流报警 + DIAGNOSIS_INPUT_LOWER, ///< 输入电流下限诊断 + DIAGNOSIS_IP_DRIVER, ///< I/P驱动诊断 + DIAGNOSIS_EEPROM_M95_1, ///< 存储器诊断 M95_1 + DIAGNOSIS_EEPROM_M95_2, ///< 存储器诊断 M95_1 + DIAGNOSIS_EEPROM_FM24, ///< 存储器诊断 FM24 + DIAGNOSIS_EEPROM_LC02, ///< 存储器诊断 LC02 + DIAGNOSIS_RTC, ///< RTC诊断 + DIAGNOSIS_MAGNET, ///< 磁条诊断 + DIAGNOSIS_MICRO_LOOP, ///< 小回路诊断 + DIAGNOSIS_PRESS_SENSOR_S, ///< 压力传感器S诊断 => 气源压力传感器故障 + DIAGNOSIS_PRESS_SENSOR_A, ///< 压力传感器A诊断 => 阀口A压力传感器故障 + DIAGNOSIS_PRESS_SENSOR_B, ///< 压力传感器B诊断 => 阀口B压力传感器故障 + DIAGNOSIS_FAIL_MAX, +} diag_fail_e; + +// 超出规格诊断 +typedef enum +{ + DIAGNOSIS_TEMPERATURE_UPPER = 0, ///< 温度上限诊断 + DIAGNOSIS_TEMPERATURE_LOWER, ///< 温度下限诊断 + DIAGNOSIS_SUPPLY_UPPER, ///< 气源压力上限诊断 + DIAGNOSIS_SUPPLY_LOWER, ///< 气源压力下限诊断 + DIAGNOSIS_SUPPLY_ERROR, ///< 气源压力偏差诊断 + DIAGNOSIS_FRICTION_UPPER, ///< 摩擦力上限诊断 + DIAGNOSIS_FRICTION_LOWER, ///< 摩擦力下限诊断 + DIAGNOSIS_ELASTICITY_UPPER, ///< 弹簧力上限诊断 + DIAGNOSIS_ELASTICITY_LOWER, ///< 弹簧力下限诊断 + DIAGNOSIS_TRAVEL_UPPER, ///< 行程上限诊断 + DIAGNOSIS_TRAVEL_LOWER, ///< 行程下限诊断 + DIAGNOSIS_TRAVEL_ERROR, ///< 行程偏差诊断 + DIAGNOSIS_SPEC_MAX, +} diag_spec_e; + +// 功能检查诊断 +typedef enum +{ + DIAGNOSIS_DRIVER_SWO1 = 0, ///< SWO1诊断 + DIAGNOSIS_DRIVER_SWO2, ///< SW O2诊断 + DIAGNOSIS_DRIVER_OUTPUT, ///< 4~20ma输出诊断 + DIAGNOSIS_CHECK_MAX, +} diag_check_e; + +// 请求维护诊断 +typedef enum +{ + DIAGNOSIS_CPU_USAGE = 0, ///< CPU使用率诊断 + DIAGNOSIS_MEM_USAGE, ///< 内存使用率诊断 + DIAGNOSIS_TRAVEL_SUM, ///< 行程累计诊断 + DIAGNOSIS_ACT_SUM, ///< 动作次数诊断 + DIAGNOSIS_DEV_REALTIME, ///< 设备时间诊断 + DIAGNOSIS_MAINT_MAX, +} diag_maint_e; + +// 诊断信息 +typedef struct +{ + uint8_t diag_state; // 状态 + uDateTime_TypeDef last_mark_time; // 故障产生时间 + uDateTime_TypeDef last_clear_time; // 故障清除时间 +} diag_msg_t; + +// 诊断记录 +typedef struct +{ + uint8_t fault_cnt; // 故障数量 + diag_msg_t *fault_msg; // 故障信息 +} diag_class_record_t; + +// 诊断结果统计 +typedef struct +{ + diag_class_e priority; // 故障最高等级 + diag_class_record_t record[DIAG_FAULT_CLASS_NUM]; // 设备故障 + alarm_handle_mode_e cmd; // 故障处理 +} diag_result_t; + +// 诊断过程参数 +typedef struct +{ + uint8_t start_tag; // 诊断开始标志 + uint32_t start_time; // 用于记录诊断起始时间 + float32 start_target; // 用于记录诊断起始目标 + float32 start_actual; // 用于记录诊断起始实际 +} diag_process_t; + +extern diag_result_t diag_result; +extern void diagnosis_init(void); ///< 诊断模块初始化 +extern void power_on_diagnosis(void); ///< 开机自检 +extern void diagnosis_inspection(void); ///< 过程诊断 +extern void diagnosis_fault_deal(void); ///< 故障处理 +extern void diagnosis_driver_swo1(float32 cmd); ///< SWO1测试 +extern void diagnosis_driver_swo2(float32 cmd); ///< SWO2测试 +extern void diagnosis_driver_output(float32 cmd); ///< PWM输出测试 +extern void diagnosis_fault_set(diag_class_e class, uint8_t code, uint8_t state); ///< 设置故障状态 +extern uint8_t get_diagnosis_fault_num(diag_class_e cls); ///< 获取故障数量 +extern state_e get_diagnosis_fault_result(diag_class_e cls, uint8_t code); ///< 获取故障状态 +#endif diff --git a/User/application/inc/fal_execution.h b/User/application/inc/fal_execution.h new file mode 100644 index 0000000..bdc332a --- /dev/null +++ b/User/application/inc/fal_execution.h @@ -0,0 +1,130 @@ +/** + * @file fal_execution.h + * @author xxx + * @date 2023-12-29 11:28:33 + * @brief + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ + +/** + * 2024-01-04 模块开发完成,测试通过 + */ +#ifndef _FAL_EXECUTION_ +#define _FAL_EXECUTION_ +#include +#include +#include "flashdb.h" + +typedef enum +{ + KEY_CALIBPARA_PARAM, + KEY_DEVICE, + KEY_HART_DEVICE_VARIABLE_PARAM, + KEY_REAL_TIME_DATA, + KEY_MODE_PARAM, // 模式参数:控制算法自定义参数 + KEY_MAX, +} fal_key_e; + +typedef enum +{ + FAL_EXECUTION_EEPROM_M95_1, + FAL_EXECUTION_EEPROM_M95_2, + FAL_EXECUTION_EEPROM_FM24, + + FAL_EXECUTION_MAX, +} fal_execution_e; + +typedef struct +{ + fal_execution_e eeprom_index; + struct fdb_kvdb kvdb; + struct fdb_tsdb tsdb; + + struct fdb_default_kv kv; + struct + { + int (*read)(uint32_t read_addr, uint8_t *data, uint16_t length); + int (*write)(uint32_t read_addr, uint8_t *data, uint16_t length); + } ops; +} fal_execution_t; + +typedef union +{ + uint8_t data; + struct + { + uint8_t M95_1 : 1; + uint8_t M95_2 : 1; + uint8_t FM24 : 1; + } bits; +} fal_execution_status_u; // eeprom状态 + +typedef struct +{ + fal_execution_status_u init; + fal_execution_status_u read; + fal_execution_status_u write; +} fal_execution_status_t; + +/** + * @brief Initializes the fal_execution module. + */ +void fal_execution_init(void); + +/** + * @brief Clears the status of a specific fal_execution. + * + * @param index The index of the fal_execution to clear. + */ +void fal_execution_clear(fal_execution_e index); + +/** + * @brief Gets the status of a specific fal_execution. + * + * @param index The index of the fal_execution to get the status from. + * @return The status of the fal_execution. + */ +BOOL fal_execution_status_get(fal_execution_e index); + +/** + * @brief Sets the status of a specific fal_execution. + * + * @param index The index of the fal_execution to set the status for. + * @param status The status to set for the fal_execution. + */ +void fal_execution_status_set(fal_execution_e index, BOOL status); + +/** + * @brief Reads data from a specific fal_execution key-value pair. + * + * @param key The key of the fal_execution key-value pair to read from. + * @param data The buffer to store the read data. + * @param length The length of the data to read. + * @return TRUE if the read operation is successful, FALSE otherwise. + */ +BOOL fal_execution_kv_read(const fal_key_e key, const uint8_t *data, uint16_t length); + +/** + * @brief Writes data to a specific fal_execution key-value pair. + * + * @param key The key of the fal_execution key-value pair to write to. + * @param data The data to write. + * @param length The length of the data to write. + * @return TRUE if the write operation is successful, FALSE otherwise. + */ +BOOL fal_execution_kv_write(const fal_key_e key, const uint8_t *const data, const uint16_t length); + +/** + * @brief Performs inspection for a specific fal_execution. + * + * @param cycle The cycle number for the inspection. + */ +void fal_execution_inspection(uint16_t cycle); + +/** + * @brief Gets the current time from the flashlight module. + * + * @return The current time from the flashlight module. + */ +fdb_time_t fal_execution_get_time(void); +#endif diff --git a/User/application/inc/key.h b/User/application/inc/key.h new file mode 100644 index 0000000..b0280cd --- /dev/null +++ b/User/application/inc/key.h @@ -0,0 +1,32 @@ +#ifndef __KEY_H__ +#define __KEY_H__ +#include "lib.h" +#include "btn.h" + +#define KEY_NONE 0x00 // 无按键 +#define KEY_ESC BIT1 // 返回 +#define KEY_UP BIT2 // 上 +#define KEY_DOWN BIT3 // 下 +#define KEY_ENT BIT4 // 确认 +#define KEY_LEFT BIT5 // 左 +#define KEY_RIGHT BIT6 // 右 +#define KEY_AUTO BIT7 // 自动 +/// 按键功能 +typedef enum +{ + KEY0 = BIT0, + KEY1 = KEY_ESC, ///< KEY1: 退出 + KEY2 = KEY_LEFT, ///< KEY2: 向左 + KEY3 = KEY_UP, ///< KEY3: 向上 + KEY4 = KEY_DOWN, ///< KEY4: 向下 + KEY5 = KEY_RIGHT, ///< KEY5: 向右 + KEY6 = KEY_ENT, ///< KEY6: 确认 + KEYAUTO = KEY_AUTO, ///< KEY_AUTO: 自动 +} button_id_e; +extern void key_botton_start(void); ///< 按键启动 +extern void key_init(void); ///< 按键初始化 +extern void key_dinit(void); ///< 按键反初始化 +extern uint64_t get_key_uuid(button_id_e k); ///< 获取按键uuid +extern void remove_key_hart_cache(void); ///< 清除按键HART缓存区 +extern BOOL key_long_press_flag(void); ///< 获取按键长按状态 +#endif ///< !__KEY_H__ diff --git a/User/application/inc/params.h b/User/application/inc/params.h new file mode 100644 index 0000000..4cd33ac --- /dev/null +++ b/User/application/inc/params.h @@ -0,0 +1,260 @@ +#ifndef __PARAMS_H__ +#define __PARAMS_H__ +#include "lib.h" +#include "main.h" +#include "entity.h" + +/// 气压通道 +typedef enum +{ + ADC_INDEX_PRESSSOURCE = 0, // 气源压力 + ADC_INDEX_PRESSOUTA = 1, // 输出压力A + ADC_INDEX_PRESSOUTB = 2, // 输出压力B + ADC_INDEX_CLOSEALL = 3, // 全部关闭 +} pressure_index_e; + +/// 定位器型号 +typedef enum +{ + POSITIONER_MODEL_GPS2000 = 2000, // 自制SAMSON + POSITIONER_MODEL_GPS2001 = 2001, // SAMSON 原装 + POSITIONER_MODEL_GPS3000 = 3000, // 自制SAMSON IP + FISHER 放大器 + POSITIONER_MODEL_GPS3001 = 3001, // FISHER 原装 + POSITIONER_MODEL_GPS5000 = 5000, +} positioner_model_e; + +/// 磁条规格 +typedef enum +{ + MAGNET_SPAC_TEST, + MAGNET_SPAC_25, + MAGNET_SPAC_50, + MAGNET_SPAC_110, + MAGNET_SPAC_210, + MAGNET_SPAC_ANGLE_90, + MAGNET_PARAM_MAX, +} magnet_spac_e; + +/// 输出开关触发逻辑 +typedef enum +{ + TRIGGER_LOGIC_DISABLE = 0, // 禁用 + TRIGGER_LOGIC_ABOVE = 1, // 高电平 + TRIGGER_LOGIC_BELOW = 2, // 低电平 +} swo_logic_e; + +/// 阀门类型 +typedef enum +{ + VALUE_TYPE_OTHER = 0, // 其它 + VALUE_TYPE_SPRING_DIAPHRAGM = 1, // 弹簧膜片式 + VALUE_TYPE_NO_SPRING_DOUBLE = 2, // 无弹簧双作用气缸式 + VALUE_TYPE_SPRING_DOUBLE = 3, // 带弹簧双作用气缸式 + VALUE_TYPE_SPRING_SINGLE = 4, // 带弹簧单作用气缸式 +} value_type_e; + +/// 阀门尺寸 +typedef enum +{ + VALUE_SIZE_OTHER = 0, // 其它 + VALUE_SIZE_34, + VALUE_SIZE_45, + VALUE_SIZE_56, +} valve_size_e; + +/// 阀门行程范围 +typedef enum +{ + VALUE_TRAVEL_OTHER = 0, // 其它 + VALUE_TRAVEL_16, + VALUE_TRAVEL_25, + VALUE_TRAVEL_40, + VALUE_TRAVEL_60, + VALUE_TRAVEL_100, + VALUE_TRAVEL_130, + VALUE_TRAVEL_160, + VALUE_TRAVEL_200, + VALUE_TRAVEL_ANGLE_60, + VALUE_TRAVEL_ANGLE_90, +} value_travel_e; + +/// 执行机构行程类型 +typedef enum +{ + TRAVEL_TYPE_STRAIGHT = 0, // 直行程 + TRAVEL_TYPE_ANGULAR = 1, // 角行程 +} value_travel_type_e; + +/// 执行机构气动类型 +typedef enum +{ + ATO = 0, // 气开,充气阀门打开,放气阀门关闭 + ATC = 1, // 气关,充气阀门关闭,放气阀门打开 +} value_action_type_e; + +/// 执行机构作用类型 +typedef enum +{ + VALVE_ACTING_SINGLE = 0, // 单作用 + VALVE_ACTING_DOUBLE = 1, // 双作用 +} value_relay_type_e; + +/// 定位器作用方向 +typedef enum +{ + CONTROLLER_ACTING_NORMAL = 0, // 正作用, I增大 -> 输出气压增大 + CONTROLLER_ACTING_REVERSE = 1, // 反作用, I增大 -> 输出气压减小 +} dev_driver_dir_e; + +/// 定位器安装方向 +typedef enum +{ + CONTROLLER_INSTALL_REVERSE = 0, // 反向安装,磁条反馈ADC值上小下大 + CONTROLLER_INSTALL_NORMAL = 1, // 正向安装,磁条反馈ADC值上大下小 +} dev_install_dir_e; + +/// 定位器工作模式 +typedef enum +{ + ON_LINE_MODE = 0, ///< 自动模式,根据4~20mA控制阀位 + OFF_LINE_MODE = 1, ///< 手动模式,根据设定目标值控制阀位 + TEST_MODE = 2, ///< 测试模式,在测试定位器部分功能时,必须在测试模式下进行 + FORBIDEN_MODE = 3, ///< 非投用模式,阀门复位,定位器禁用信号控制功能 + WAIT_MODE = 4, ///< 待机模式,阀门保持,定位器禁用信号控制功能 +} dev_work_mode_e; + +/// 定位器控制模式 +typedef enum +{ + POS_CTRL_MODE = 0, ///< 位置控制模式 + PRESS_CTRL_MODE = 1, ///< 压力控制模式 +} dev_ctrl_mode_e; + +/// 阀门特性 +typedef enum +{ + VALVE_CHARACT_LINEAR = 0, // 线性 + VALVE_CHARACT_EQU50 = 1, // 等百1:50 + VALVE_CHARACT_QOPEN50 = 2, // 快开1:50 + VALVE_CHARACT_EQU25 = 3, // 等百1:25 + VALVE_CHARACT_QOPEN25 = 4, // 快开1:25 + VALVE_CHARACT_EQU33 = 5, // 等百1:33 + VALVE_CHARACT_QOPEN33 = 6, // 快开1:33 + VALVE_CHARACT_SElF = 7, // 自定义 +} valve_chart_e; + +/// LCD显示方向 +typedef enum +{ + DISP_DIR_0 = 0, + DISP_DIR_180 = 1, +} display_direction_e; + +/// LCD显示语言 +typedef enum +{ + CHINESE = 0, + ENGLISH = 1, +} display_language_e; + +/// 行程显示方式 +typedef enum +{ + TRAVEL_DISPLAY_NORMAL = 0, // 正向显示,与阀门开度一致 + TRAVEL_DISPLAY_REVERSE = 1, // 反向显示,与阀门开度相反 +} display_travel_mode_e; + +/// 行程单位 +typedef enum +{ + TRAVEL_UNIT_PRE = 0, // 百分比 + TRAVEL_UNIT_MM = 1, // 毫米 + TRAVEL_UNIT_INCH = 2, // 英寸 + TRAVEL_UNIT_ANGLE = 3, // 角度 +} travel_unit_e; + +/// 压力单位 +typedef enum +{ + PRESSURE_UNIT_Kpa = 0, + PRESSURE_UNIT_Mpa = 1, + PRESSURE_UNIT_Psi = 2, + PRESSURE_UNIT_Bar = 3, + PRESSURE_UNIT_Kgf = 4, +} press_unit_e; + +/// 温度单位 +typedef enum +{ + TEMPERATURE_UNIT_C = 0, // 摄氏度 + TEMPERATURE_UNIT_F = 1, // 华氏度 +} temperature_unit_e; + +/// 电流单位 +typedef enum +{ + CURRENT_UNIT_MA = 0, // 毫安 + CURRENT_UNIT_A = 1, // 安 +} current_unit_e; + +/// 电流单位 +typedef enum +{ + FORCE_UNIT_N = 0, // 牛 + FORCE_UNIT_KN = 1, // 千牛 +} force_unit_e; + +/// 报警处理方式 +typedef enum +{ + ALARM_HANDLING_CONTINUE = 0, // 不影响阀门动作 + ALARM_HANDLING_KEEP = 1, // 阀门位置保持 + ALARM_HANDLING_RESET = 2, // 阀门复位 +} alarm_handle_mode_e; + +/// 复位处理方式 +typedef enum +{ + RESET_HANDLING_CONTINUE = 0, // 自动控制 + RESET_HANDLING_PAUSE = 1, // 控制阀门到上次位置 +} reset_handle_mode_e; + +/// PID参数选择 +typedef enum +{ + Adaptive_PID = 0, // 自适应PID + Self_PID = 1, // 自定义PID +} pid_index_e; + +/// 整定结果 +typedef enum +{ + TUNED_NONE = 0, // 未整定 + TUNED_ONGOING = 1, // 整定中 + TUNED_SUCCESS = 2, // 整定成功 + TUNED_FAILED = 3, // 整定失败 +} tuned_result_e; + +// TODO 气压传感规格 +typedef enum +{ + PRESSURE_PARAM_S, + PRESSURE_PARAM_A, + PRESSURE_PARAM_B, + PRESSURE_PARAM_MAX, +} pressure_type_e; + +/// 磁条规格 [0]:最小值 [1]:最大值 +extern const uint16_t magnet_param_table[MAGNET_PARAM_MAX][2]; +/// 气压传感规格 [0]:最小值 [1]:最大值 +extern const uint16_t pressure_param_table[PRESSURE_PARAM_MAX][2]; +/// 阀门流量特性表 +extern const uint16_t valve_characteristics_table[][17]; + +extern void params_init(void); +extern void params_restart(void); +extern void hart_attribute_params_restart(void); +extern void hart_attribute_params_map(void); + +extern uint16_t get_pwm_arr_default(void); +#endif // __PARAMS_H__ diff --git a/User/application/inc/pdctrl.h b/User/application/inc/pdctrl.h new file mode 100644 index 0000000..55bb443 --- /dev/null +++ b/User/application/inc/pdctrl.h @@ -0,0 +1,68 @@ +#ifndef _PDCTRL_H_ +#define _PDCTRL_H_ +#include "lib.h" +#include "bsp.h" + +#define PWM_WID 26 // PWM正频宽 +#define PDCTRL_PWM_PRESCALER (1) // 预分频系数 +#define PDCTRL_PWM_FREQUENCY (4 * 1000) // 主频,KHZ +#define PDCTRL_PWM_TIM (TIM2) // 定时器 +#define PDCTRL_PWM_TIM_IRQn (TIM2_IRQn) // 中断 +#define PDCTRL_PWM_CHINNEL (LL_TIM_CHANNEL_CH4) // 通道 +#define PDCTRL_PWM_GPIO_Port (PWM_CONTROL_GPIO_Port) // 输出引脚 +#define PDCTRL_PWM_Pin (PWM_CONTROL_Pin) // 输出引脚 + +#define PDCTRL_DAC_TIM_IRQn (TIM6_IRQn) // 中断 +#define PDCTRL_DAC_CHINNEL (LL_DAC_CHANNEL_2) // 通道 +#define PDCTRL_DAC_GPIO_Port (DAC_CONTROL_GPIO_Port) // 输出引脚 +#define PDCTRL_DAC_Pin (DAC_CONTROL_Pin) // 输出引脚 + +#define PDCTRL_PWMP_TIM (TIM2) // 定时器 +#define PDCTRL_PWMP_TIM_IRQn (TIM2_IRQn) // 中断 +#define PDCTRL_PWMP_CHINNEL (LL_TIM_CHANNEL_CH4) // 通道 +#define PDCTRL_PWMP_GPIO_Port (PWM_CONTROL_GPIO_Port) // 输出引脚 +#define PDCTRL_PWMP_Pin (PWM_CONTROL_Pin) // 输出引脚 + +typedef enum +{ + PDCTRL_DAC = 1, // DAC输出模式 + PDCTRL_PWM = 2, // PWM变频输出模式 + PDCTRL_PWMP = 3, // PWM占空比模式 +} pdctrl_mode_e; + +typedef enum +{ + MODE_PLAN_1, // samson IP+fisher 放大器 + MODE_PLAN_2, // samson IP+活塞放大器 +} mode_plan_e; + +typedef struct +{ + __IO uint16_t last_out; + uint16_t pwm_arr_default; + + uint32_t sysclk; + uint8_t pwm_wid; // PWM正频宽 + uint32_t psc; // 预分频系数 + uint32_t arr; + float32 freq; + float32 arr_us; + float32 duty_percent; +} pdctrl_t; + +extern pdctrl_t pdctrl_data; + +void pdctrl_init(pdctrl_mode_e mode); ///< 控制器初始化 +void pdctrl_out(uint16_t out); ///< 控制器输出 +void pdctrl_pwm_set_arr(uint32_t arr); ///< 动态修改频率 +void pdctrl_set_pwm_wid(uint16_t wid); ///< 设置PWM正频宽 +uint16_t calculate_pwm_duty(uint32_t arr); ///< 变频计算占空比 +uint16_t pdctrl_pwm_duty_convert_ccr(float32 pwm_duty); ///< 占空比转换为CCR值 +float32 pdctrl_pwm_get_duty_percent(uint32_t arr); ///< 获取占空比 + +void pdctrl_stop(void); ///< 控制停止 +void pdctrl_run(void); ///< 控制运行 +uint8_t get_pdctrl_mode(void); ///< 获取控制模式 +pdctrl_t *pdctrl_get(void); ///< 获取控制器 + +#endif // _PDCTRL_H_ diff --git a/User/application/mode/mode.c b/User/application/mode/mode.c new file mode 100644 index 0000000..d3c7d5b --- /dev/null +++ b/User/application/mode/mode.c @@ -0,0 +1,337 @@ +/** + * @file mode.c + * @author xxx + * @date 2023-09-18 10:00:52 + * @brief 此文件用于实现不同工作模式的功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include +#include "app.h" +#include "main.h" +#include "mode.h" + +mode_params_t mode_params; // 模式参数 +static mode_t _mode; + +static uint8_t deal_dev_work_mode(void) +{ + uint8_t mode = udevice.dev_work_mode; + + if (udevice.dev_work_mode == FORBIDEN_MODE || udevice.dev_work_mode == TEST_MODE) + { + return mode; + } + else + { + + return mode; + } +} + +/** + * @brief 改变自动重装载寄存器的值 + * @param {uint16_t} autoload + * @return {*} + * @note + */ +static void mode_autoload_change(uint16_t autoload) +{ + LL_TIM_SetAutoReload(TIM7, autoload); +} + +/** + * @brief 工作模式参数保存,回调处理 + * @return {*} + * @note + */ +static void mode_params_save_cb(void) +{ + fal_execution_kv_write(KEY_CALIBPARA_PARAM, (uint8_t *)&calib_param, (CALIBPARA_NUM * sizeof(calib_param_t))); + fal_execution_kv_write(KEY_MODE_PARAM, (uint8_t *)&mode_params, sizeof(mode_params_t)); + fal_execution_kv_read(KEY_MODE_PARAM, (uint8_t *)&mode_params, sizeof(mode_params_t)); +} + +/** + * @brief 测试模式 + * @return {*} + * @note + */ +void mode_test_process(void) +{ + switch (mode_get()->test_project) + { + case MODE_DIAGNOSIS: // EPM特性诊断 + mode_get()->ctrl.state = FALSE; + flow_event = FLOW_EVENT_DIAGNOSIS; + break; + default: + break; + } +} + +/** + * @brief 行程统计(100ms以上运行一次) + * @return {*} + * @note + */ +void mode_travel_statistics(void) +{ + static float32 loop_current_last = 0.0f; // 上一次的电流 + static uint8_t change_count = 0; + float32 loop = 0.0; + // 输入电流 + loop = get_current(); + rt_data.loop_current = get_current_deal(loop); + // 过滤掉不稳定的电流值 + if (loop_current_last != rt_data.loop_current) + { + if (change_count++ >= 2) + { + loop_current_last = rt_data.loop_current; + change_count = 0; + } + else + { + return; + } + } + else + { + change_count = 0; + lpf_window_reset(mode_get()->show_loop_lpf); + lpf_window_reset(mode_get()->show_actual_lpf); + } + + // 获取目标行程 + if (mode_get()->ctrl.mode == ON_LINE_MODE) // 在线模式 + { + rt_data.target_travel = i2psb(rt_data.loop_current); + rt_data.target_travel = (uint16_t)(rt_data.target_travel * 10) * 0.1f; + } + else if (mode_get()->ctrl.mode == OFF_LINE_MODE) // 离线模式 + { + rt_data.target_travel = udevice.travel_setpoint; + } + else if (mode_get()->ctrl.mode == TEST_MODE) // 测试模式 + { + } + + // 目标行程处理 + rt_data.target_travel = target_travel_deal(rt_data.target_travel); + pid_target = get_pid_travel(rt_data.target_travel); + show_target = get_show_travel(rt_data.target_travel); + + // 实际行程处理 + rt_data.actual_travel = actual_travel_deal(rt_data.actual_travel); + show_actual = get_show_travel(rt_data.actual_travel); + // show_actual = lpf_window_update(mode_get()->show_actual_lpf, show_actual); + show_actual = kalman_update(&mode_get()->show_actual_kalman, show_actual); + show_loop = lpf_window_update(mode_get()->show_loop_lpf, rt_data.loop_current); +} + +/** + * @brief 气压统计 + * @return {*} + * @note + */ +static void pressure_statistics(void) +{ + if (udevice.press_sensor_enable != TRUE) + { + return; + } + static uint8_t id = ADC_INDEX_CLOSEALL; + switch (id) + { + case ADC_INDEX_PRESSSOURCE: + rt_data.pressure_s = get_pressure(ADC_INDEX_PRESSSOURCE); + id = ADC_INDEX_PRESSOUTA; + BP_S_POWER_OFF(); + BP_A_POWER_ON(); + break; + case ADC_INDEX_PRESSOUTA: + rt_data.pressure_a = get_pressure(ADC_INDEX_PRESSOUTA); + id = ADC_INDEX_PRESSOUTB; + BP_A_POWER_OFF(); + BP_B_POWER_ON(); + break; + case ADC_INDEX_PRESSOUTB: + rt_data.pressure_b = get_pressure(ADC_INDEX_PRESSOUTB); + id = ADC_INDEX_PRESSSOURCE; + BP_B_POWER_OFF(); + BP_S_POWER_ON(); + break; + case ADC_INDEX_CLOSEALL: + id = ADC_INDEX_PRESSSOURCE; + BP_S_POWER_ON(); + break; + default: + break; + } +} + +/** + * @brief 算法控制模块 + * @return {*} + * @note 该模块在TIM7中执行 + */ +void mode_process(void) +{ + pressure_statistics(); // 气压轮询读取 + + if (mode_get()->ctrl.state == FALSE) // 不进行算法控制 + { + return; + } + + // travel_statistics因为在flow中被更新,如果UI更新时会导致延时,所以在这里更新 + // 系统的tick是10ms一次,200ms更新一次数据 + if (FALSE == mode_get()->interface_req.mode_is_adjusting()) + { + if (sys_get_tick() - mode_get()->alog_control_ticks >= 20) // 200ms + { + mode_get()->alog_control_ticks = sys_get_tick(); + mode_travel_statistics(); + } + } + else + { + if (sys_get_tick() - mode_get()->alog_control_ticks >= 100) // 1000ms + { + mode_get()->alog_control_ticks = sys_get_tick(); + mode_travel_statistics(); + } + } + + // 当电流达到4mA时才进行控制 + if (rt_data.loop_current >= LOOP_CURRENT_MIN) + { + if (udevice.dev_algorithm_mode == MODE_CONSTANT_CONTROL_ALGORITHM) + { + } + else if (udevice.dev_algorithm_mode == MODE_SPEED_CONTROL_ALGORITHM) + { + } + else if (udevice.dev_algorithm_mode == MODE_FREQUENCY_DOMAIN_CONTROL_ALGORITHM) + { + mode_pwmp_hd_process(); + } + else if (udevice.dev_algorithm_mode == MODE_VARIABLE_FREQUENCY_CONTROL_ALGORITHM) + { + } + else + { + DBG_ASSERT(FALSE __DBG_LINE); + } + } + else + { + pdctrl_out(0); + } +} + +/** + * @brief 模式处理 + * @param {uint8_t} work_mode + * @return {*} + * @note + */ +void mode_detection(void) +{ + mode_get()->ctrl.mode = deal_dev_work_mode(); + + switch (mode_get()->ctrl.mode) + { + case ON_LINE_MODE: + case OFF_LINE_MODE: + case WAIT_MODE: + if (mode_get()->ctrl.state != TRUE) + { + mode_get()->ctrl.state = TRUE; + pdctrl_run(); // 输出软使能 + } + break; + case FORBIDEN_MODE: + if (mode_get()->ctrl.state != FALSE) + { + mode_get()->ctrl.state = FALSE; + pdctrl_stop(); // 输出软禁止 + } + break; + case TEST_MODE: + mode_get()->ctrl.state = FALSE; + mode_test_process(); + break; + default: + break; + } +} + +/** + * @brief 工作模式初始化 + * @return {*} + * @note + */ +void mode_init(void) +{ + osel_memset((uint8_t *)&_mode, 0, sizeof(mode_t)); + + mode_get()->positioner_model = udevice.dev_model; + mode_get()->alog_control_ticks = sys_get_tick(); + mode_autoload_change(mode_default_autoload); + + // 反初始化,释放内存 + + mode_pwmp_hd_dinit(); + + switch (udevice.dev_algorithm_mode) + { + case MODE_CONSTANT_CONTROL_ALGORITHM: + pdctrl_init(PDCTRL_DAC); + break; + case MODE_SPEED_CONTROL_ALGORITHM: + pdctrl_init(PDCTRL_PWMP); + break; + case MODE_FREQUENCY_DOMAIN_CONTROL_ALGORITHM: + pdctrl_init(PDCTRL_PWMP); + mode_pwmp_hd_init(&mode_get()->interface_req, mode_get()->positioner_model, &mode_params.mode_pwmp_hd_params, + mode_params_save_cb); + break; + case MODE_VARIABLE_FREQUENCY_CONTROL_ALGORITHM: + pdctrl_init(PDCTRL_PWM); + break; + default: + DBG_ASSERT(FALSE __DBG_LINE); + break; + } + + DBG_ASSERT(mode_get()->interface_req.mode_process_start != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_process_stop != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_adjust_start != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_adjust_stop != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_get_adjust_data != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_adjust_result != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_adjust_step_count != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_adjust_step_current != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_control_idle != NULL __DBG_LINE); + DBG_ASSERT(mode_get()->interface_req.mode_is_adjusting != NULL __DBG_LINE); + + mode_get()->show_loop_lpf = lpf_window_init(10); + mode_get()->show_actual_lpf = lpf_window_init(10); + + kalman_init(&mode_get()->loop_kalman); + kalman_init(&mode_get()->show_actual_kalman); + mode_get()->loop_kalman.filter_limit = 0.3f; + mode_get()->show_actual_kalman.filter_limit = 0.3f; +} + +/** + * @brief 工作模式获取 + * @return {*} + * @note + */ +mode_t *mode_get(void) +{ + return &_mode; +} diff --git a/User/application/mode/mode.h b/User/application/mode/mode.h new file mode 100644 index 0000000..53e372c --- /dev/null +++ b/User/application/mode/mode.h @@ -0,0 +1,69 @@ +/** + * @file mode.h + * @author xxx + * @date 2023-09-18 10:37:29 + * @brief + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __MODE_H__ +#define __MODE_H__ + +#include "lib.h" +#include "filter.h" +#include "mode_def.h" + +#include "mode_pwmp_hd.h" + + +typedef enum +{ + MODE_CONSTANT_CONTROL_ALGORITHM, ///< 恒定控制算法 gaopengjie + MODE_VARIABLE_FREQUENCY_CONTROL_ALGORITHM, ///< 变频控制算法 xushenghao + MODE_SPEED_CONTROL_ALGORITHM, ///< 速度控制算法 zhangxiaoming + MODE_FREQUENCY_DOMAIN_CONTROL_ALGORITHM, ///< 频域控制算法 hangdian +} mode_algorithm_e; + +/// 测试项目 +typedef enum +{ + NO_TEST_PROJECT = 0, // 无测试项目 + MODE_DIAGNOSIS = 1, // 性能诊断 + MANUAL_TEST = 2, // 手动按键测试 + TEST_PROJECT_MAX, +} test_project_e; + +typedef struct +{ + mode_pwmp_hd_params_u mode_pwmp_hd_params; ///< PWMP HD模式参数 +} mode_params_t; + +typedef struct +{ + BOOL state; // TRUE:算法控制器可以运行 FALSE:算法控制器不可以运行 + uint8_t mode; // 模式 +} mode_ctrl_t; + +typedef struct +{ + mode_interface_req_t interface_req; ///< 模式接口请求 + + // 内部变量 + uint16_t positioner_model; ///< 定位器型号 + __IO test_project_e test_project; ///< 测试项目 + __IO mode_ctrl_t ctrl; ///< 控制器 + __IO uint32_t alog_control_ticks; ///< 算法控制数据刷新计数器 + lpf_window_t *show_loop_lpf; + lpf_window_t *show_actual_lpf; + kalman_t loop_kalman; + kalman_t show_actual_kalman; +} mode_t; + +extern void mode_init(void); ///< 工作模式初始化 +extern mode_t *mode_get(void); ///< 获取工作模式 +extern void mode_detection(void); ///< 工作模式处理 +extern void mode_travel_statistics(void); ///< 行程统计 +extern void mode_process(void); ///< 算法控制模块 +extern void mode_test_process(void); ///< 测试模式处理 + +#endif diff --git a/User/application/mode/mode_def.h b/User/application/mode/mode_def.h new file mode 100644 index 0000000..5ebc92c --- /dev/null +++ b/User/application/mode/mode_def.h @@ -0,0 +1,96 @@ +#ifndef __MODE_DEF_H__ +#define __MODE_DEF_H__ + +#define MODE_DIAGNOSIS_STORAGE_SIZE (12 * 1024) // 诊断存储空间大小 +#define DIAGNOSIS_EPM_DBG 0 // 测试:诊断EPM调试 + +typedef struct +{ + uint16_t pos0; ///< 位置0 ad + uint16_t pos100; ///< 位置100 ad + uint16_t pot0; ///< 位置0 输出 + uint16_t pot100; ///< 位置100 输出 + uint16_t current0; ///< 位置0 电流(毫安,放大100倍, 0.01ma=1) + uint16_t current100; ///< 位置100 电流(毫安,放大100倍,0.01ma=1) + uint16_t open_time; ///< 全开时间(秒) + uint16_t close_time; ///< 全关时间(秒) + float32 kp; ///< pid 比例系数 + float32 ki; ///< pid 积分系数 + float32 kd; ///< pid 微分系数 +} mode_adjust_data_t; + +typedef enum +{ + POSITION_CHANGE, // 位置发生变化 + POSITION_NO_CHANGE, // 位置没变化,但是等待次数没到 + POSITION_NO_CHANGE_FOREVER, // 位置不再发生变化 +} valve_position_change_e; // 位置变化 + +typedef enum +{ + VALUE_POSITION_MIN, // 位置值最小 + VALUE_POSITION_MAX, // 位置值最大 +} mode_pwm_value_position_e; // 位置值 + +typedef enum +{ + // 这一部分只用于LCD整定界面 + LCD_ADJUST_IDEL = 1, // 准备中 + LCD_ADJUST_POSITION0, // 位置0 + LCD_ADJUST_POSITION100, // 位置100 + LCD_ADJUST_TIMER, // 计时 + LCD_ADJUST_TUNING, // 自整定 + LCD_ADJUST_SAVE, // 存储变量 + LCD_ADJUST_STOP, // 停止 +} lcd_adjust_step_e; // 整定步骤 + +typedef enum +{ + MODE_DIAGNOSIS_EPM_STEP_ANCHOR_POINT = 1, // 第一步先找锚点 + MODE_DIAGNOSIS_EPM_STEP_AERATE = 2, // 最大充气时间 + MODE_DIAGNOSIS_EPM_STEP_BLEEDING = 3, // 最大放气时间 + MODE_DIAGNOSIS_EPM_STEP_CONTROL = 4, // 控制 +} mode_diagnosis_epm_step_e; + +typedef enum +{ + MODE_DIAGNOSIS_RUNING, // 诊断运行中 + MODE_DIAGNOSIS_FINISH, // 诊断结束 + MODE_DIAGNOSIS_FAIL, // 诊断失败 +} mode_diagnosis_runing_state_e; + +typedef struct +{ + BOOL enabled; // 是否使能 + float current_trip; // 当前行程 + float drive_output; // 驱动输出 + float pressure_A; // A口压力 + float pressure_B; // B口压力 + float feedback_current; // 反馈电流 + + // decompression的数据 + int32_t decompression_current_trip; // 当前行程 + int32_t decompression_drive_output; // 驱动输出 + int32_t decompression_pressure_A; // A口压力 + int32_t decompression_pressure_B; // B口压力 + int32_t decompression_feedback_current; // 反馈电流 +} mode_diagnosis_epm_data_t; // epm诊断需要采集的数据 + +typedef struct +{ + void (*mode_process_stop)(void); // 停止:停止算法控制和整定,流程进入等待状态 + void (*mode_process_start)(void); // 启动:开始算法控制 + void (*mode_adjust_start)(void); // 整定开始 + void (*mode_adjust_stop)(void); // 整定结束 + void (*mode_get_adjust_data)(mode_adjust_data_t *data); // 获取整定数据 + uint8_t (*mode_adjust_result)(void); // 整定开始后:获取整定结果 + uint8_t (*mode_adjust_step_count)(void); // 获取整定步骤数量 + uint8_t (*mode_adjust_step_current)(void); // 获取当前整定步骤 + + BOOL(*mode_control_idle) + (void); // 控制是否空闲 + BOOL(*mode_is_adjusting) + (void); // 是否正在整定 + +} mode_interface_req_t; +#endif // __MODE_DEF_H__ diff --git a/User/application/mode/mode_pwmp_hd.c b/User/application/mode/mode_pwmp_hd.c new file mode 100644 index 0000000..0b72d9b --- /dev/null +++ b/User/application/mode/mode_pwmp_hd.c @@ -0,0 +1,1773 @@ +#include +#include +#include "sys.h" +#include "dacs.h" +#include "board.h" +#include "./mode_pwmp_hd.h" +#include "delay.h" +#include "at_hc24.h" +#include "entity.h" +#include "eeprom_m95.h" +#include "pid.h" +#include "filter.h" +#include +#include +#include "pdctrl.h" +#include "app.h" +#include "data_type_def.h" + +#define ACTUAL_FILTER 0 + +mode_pwmp_hd_t *mode_pwmp_hd; +pwmp_hd_adjust_t *mode_pwmp_hd_adjust; +pid_autotune_hd_t *pid_autotune_hd; +pwmp_hd_test_t *mode_pwmp_hd_test; +execute_rsp_hd_t rsp; // 执行结果 + +static execute_rsp_hd_t *execute_dac_plan1(void); // 执行方案1 +static execute_rsp_hd_t *execute_dac_plan2(void); // 执行方案2 +static execute_rsp_hd_t *execute_dac_plan3(void); // 执行方案3 +static execute_rsp_hd_t *execute_dac_plan4(void); // 执行方案4 +// static uint8_t execute_run_count = 0; // 执行计数 + +static void _process_start(void) +{ + pwmp_hd_process_state_set(PWMP_HD_PROCESS_CONTROL); +} + +static void _process_stop(void) +{ + pwmp_hd_process_state_set(PWMP_HD_PROCESS_STOP); +} + +static void _adjust_start(void) +{ + pwmp_hd_process_state_set(PWMP_HD_PROCESS_ADJUST); +} + +static void _adjust_stop(void) +{ + pwmp_hd_process_state_set(PWMP_HD_PROCESS_ADJUST_STOP); +} + +static uint8_t _adjust_result(void) +{ + if (mode_pwmp_hd->process_state == PWMP_HD_PROCESS_ADJUST) + { + return TUNED_ONGOING; + } + else + { + return mode_pwmp_hd->pwmp_save->storage.tuned_flag; + } +} + +static uint8_t _adjust_step_count(void) +{ + return LCD_ADJUST_STOP; +} + +static uint8_t _adjust_step_current(void) +{ + return LCD_ADJUST_IDEL; +} + +static void _adjust_data(mode_adjust_data_t *data) +{ + // data->pos0 = mode_control->storage_data->storage.ad_0; ///< 位置0 ad + // data->pos100 = mode_control->storage_data->storage.ad_100; ///< 位置100 ad + // data->pot0 = mode_control->storage_data->storage.aerate_min_arr; ///< 位置0 输出 + // data->pot100 = mode_control->storage_data->storage.aerate_max_arr; ///< 位置100 输出 + // data->current0 = mode_control->storage_data->storage.aerate_min_current; ///< 位置0 电流(毫安,放大100倍, 0.01ma=1) + // data->current100 = mode_control->storage_data->storage.aerate_max_current; ///< 位置100 电流(毫安,放大100倍,0.01ma=1) + // data->open_time = mode_control->storage_data->storage.all_open_time; ///< 全开时间(秒) + // data->close_time = mode_control->storage_data->storage.all_close_time; ///< 全关时间(秒) + // data->kp = mode_control->storage_data->storage.kp; ///< pid 比例系数 + // data->ki = mode_control->storage_data->storage.ki; ///< pid 积分系数 + // data->kd = mode_control->storage_data->storage.kd; ///< pid 微分系数 +} + +static BOOL _control_idle(void) +{ + return TRUE; +} + +static BOOL _adjust_isrun(void) +{ + return mode_pwmp_hd->process_state == PWMP_HD_PROCESS_ADJUST; +} + +/*程序状态设置*/ +void pwmp_hd_process_state_set(mode_pwmp_hd_process_state_e state) +{ + if (mode_pwmp_hd->process_state == state && mode_pwmp_hd->adjust_state == PWMP_HD_PROCESS_ADJUST) + { + mode_pwmp_hd->process_state = PWMP_HD_PROCESS_STOP; + } + else + { + mode_pwmp_hd->process_state = state; + switch (state) + { + case PWMP_HD_PROCESS_ADJUST: + mode_pwmp_hd->adjust_state = PWMP_HD_ADJUST_IDEL; + break; + default: + break; + } + } +} + +/*行程更新*/ +static void pwmp_control_update(filter_e type) +{ + mode_pwmp_hd_control_t *p = &mode_pwmp_hd->control; + rt_data.actual_travel = get_actual_travel(type); + rt_data.actual_travel = actual_travel_deal(rt_data.actual_travel); + pid_actual = get_pid_travel(rt_data.actual_travel); + + if (mode_pwmp_hd->process_state == PWMP_HD_PROCESS_ADJUST) + { + p->ctrl_target = p->ctrl_target; + } + else if (mode_pwmp_hd->process_state == PWMP_HD_PROCESS_TEST) + { + p->ctrl_target = mode_pwmp_hd_test->ctrl_target; + } + else + { + p->ctrl_target = lpf_window_update(mode_pwmp_hd->filter.handle, pid_target); + } +#if ACTUAL_FILTER == 1 + if (fabs(p->real_error) < 0.5) + { + p->ctrl_feedback = lpf_window_update(mode_pwmp_hd->filter.handle, pid_actual); + } + else + { + p->ctrl_feedback = pid_actual; + lpf_window_reset(mode_pwmp_hd->filter.handle); + } +#else + p->ctrl_feedback = pid_actual; +#endif + p->real_error = p->ctrl_target - p->ctrl_feedback; + p->current_adc = adc_raw[ADC_PSB_CHANNEL]; + p->small_trip_current_adc = adc_result_average(ADCS_1, ADC_IPSB_CHANNEL); + /*测试模式赋值*/ + mode_pwmp_hd_test->psb_adc = p->current_adc; + mode_pwmp_hd_test->small_trip_current_adc = p->small_trip_current_adc; + mode_pwmp_hd_test->ctrl_feedback = p->ctrl_feedback; + mode_pwmp_hd_test->real_error = p->real_error; +} + +/*PID参数获取*/ +static float32 get_pwmp_hd_control_kp(void) +{ + if (mode_pwmp_hd->pwmp_save->storage.kp < 2) + { + // return mode_pwmp_hd->pwmp_save->storage.kp * 8; + return mode_pwmp_hd->pwmp_save->storage.kp * 15; + } + else + { + return mode_pwmp_hd->pwmp_save->storage.kp * 4; + } +} + +static float32 get_pwmp_hd_control_ki(void) +{ + return mode_pwmp_hd->pwmp_save->storage.ki < 0.001 ? mode_pwmp_hd->pwmp_save->storage.ki * 10 : 0.01; + // return mode_pwmp_hd->pwmp_save->storage.ki; +} + +static float32 get_pwmp_hd_control_kd(void) +{ + // return mode_pwmp_hd->pwmp_save->storage.kd < 0.01 ? mode_pwmp_hd->pwmp_save->storage.kd : 0.001; + return mode_pwmp_hd->pwmp_save->storage.kd; +} + +/*将自己结构体变量中的参数保存到公共参数中*/ +static void pwmp_public_params_update() +{ + udevice.pos0_travel_vol = mode_pwmp_hd->pwmp_save->storage.trip_0; + udevice.pos100_travel_vol = mode_pwmp_hd->pwmp_save->storage.trip_100; + udevice.output_min = mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin; + udevice.output_max = mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin; + udevice.apid_kp = mode_pwmp_hd->pwmp_save->storage.kp; + udevice.apid_ki = mode_pwmp_hd->pwmp_save->storage.ki; + udevice.apid_kd = mode_pwmp_hd->pwmp_save->storage.kd; + udevice.tuned_flag = mode_pwmp_hd->pwmp_save->storage.prov_flag; +} + +/*程序反初始化*/ +void mode_pwmp_hd_dinit(void) +{ + if (mode_pwmp_hd != NULL) + { + pwmp_hd_process_state_set(PWMP_HD_PROCESS_STOP); + osel_mem_free(mode_pwmp_hd); + mode_pwmp_hd = NULL; + } +} + +//////////////////////////////*控制BEGIN*////////////////////////////////////////////////////// + +/** + * @brief 算法方案初始化 + * @param {execute_plan_hd_e} plan + * @return {*} + * @note + */ +void execute_pid_init(execute_plan_hd_e plan) +{ + switch (plan) + { + // HD:位置式PID算法 + case EXECUTE_PLAN_1: + _pid.type = PID_TYPE_CUSTOM_HANGDIAN; + pid_constructor(&_pid); + _pid.pid_u.hd.set_ctrl_prm_position(&_pid.pid_u.hd, get_pwmp_hd_control_kp(), get_pwmp_hd_control_ki(), get_pwmp_hd_control_kd()); + break; + case EXECUTE_PLAN_2: + + break; + case EXECUTE_PLAN_3: + + break; + case EXECUTE_PLAN_4: + + default: + break; + } +} + +/** + * @brief 算法方案执行 + * @param {execute_plan_hd_e} plan + * @return {*} + * @note + */ +execute_rsp_hd_t *execute_dac(execute_plan_hd_e plan) +{ + switch (plan) + { + case EXECUTE_PLAN_1: + return execute_dac_plan1(); // 位置式PID + case EXECUTE_PLAN_2: + return execute_dac_plan2(); + case EXECUTE_PLAN_3: + return execute_dac_plan3(); + case EXECUTE_PLAN_4: + return execute_dac_plan4(); + default: + rsp.code = EXECUTE_HD_NONE; + return &rsp; + } +} +static execute_rsp_hd_t *execute_dac_plan1() +{ + static float32 index_min = 0.4; // 加权系数 + static float32 index_max = 0.8; + static float32 Control_diff; + // uint8_t flag_stable = 0; + Control_diff = mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin - mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin; + float32 out = 0.0; + + // 杭电:输出限幅的参数设置 + _pid.pid_u.hd.set_out_prm_position(&_pid.pid_u.hd, 100, 0); + + out = _pid.pid_u.hd.pid_position(&_pid.pid_u.hd, mode_pwmp_hd->control.real_error); + out = out / 100; // 对PID输出结果进行归一化处理 + out *= (mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin + Control_diff * index_max) - (mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin - Control_diff * index_min); // 映射实际控制器的范围 + out += mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin - Control_diff * index_min; // 对输出结果进行偏移处理 + + rsp.code = EXECUTE_HD_OUT; + rsp.dac = (uint32_t)out; + + /* + /// 在执行了十次之后若系统认为稳定进入以下程序进行微调(非线性补偿器) + if (execute_run_count >= 10) + { + if ( rt_data.actual_travel < target_travel) + { + if (fabs(mode_pwmp_hd->control.real_error) <= 0.5) + { + if (flag_stable == 1) + { + rsp.dac -= 0; + flag_stable = 0; + } + execute_run_count = 0; + } + else + { + if (fabs(mode_pwmp_hd->control.real_error) < 1) + { + // rsp.dac += (fabs(mode_pwmp_hd->control.real_error) * 40); + rsp.dac += (fabs(mode_pwmp_hd->control.real_error) * 0); + flag_stable = 1; + } + else if (fabs(mode_pwmp_hd->control.real_error) < 5) + { + // rsp.dac += (fabs(mode_pwmp_hd->control.real_error) * 30); + rsp.dac += (fabs(mode_pwmp_hd->control.real_error) * 0); + } + else + { + execute_run_count = 0; + } + } + } + if (target_travel <= rt_data.actual_travel) + { + // 若进入死区范围,那么停止计数,停止微调 + if (fabs(mode_pwmp_hd->control.real_error) <= 0.5) + { + if (flag_stable == 1) + { + rsp.dac += 0; + flag_stable = 0; + } + execute_run_count = 0; + } + else + { + if (fabs(mode_pwmp_hd->control.real_error) < 1) + { + rsp.dac += -(fabs(mode_pwmp_hd->control.real_error) * 0); + // rsp.dac += -(fabs(mode_pwmp_hd->control.real_error) * 40); + flag_stable = 1; + } + else if (fabs(mode_pwmp_hd->control.real_error) < 5) + { + // rsp.dac += -(fabs(mode_pwmp_hd->control.real_error) * 30); + rsp.dac += (fabs(mode_pwmp_hd->control.real_error) * 0); + } + else + { + execute_run_count = 0; + } + // execute_run_count = 2; + } + } + } + else + { + execute_run_count++; + } + */ + + return &rsp; +} + +///

+/// +/// +/// +/// + +static execute_rsp_hd_t *execute_dac_plan2() +{ + return 0; +} + +/// +/// +/// +/// + +static execute_rsp_hd_t *execute_dac_plan3() +{ + return 0; +} + +/// +/// +/// +/// +static execute_rsp_hd_t *execute_dac_plan4() +{ + return 0; +} +//////////////////////////////*控制END*////////////////////////////////////////////////////// + +//////////////////////////////*整定相关函数BEGIN*////////////////////////////////////////////////////// +/*PID自整定方法*/ +static void pid_autotune_way_set(pid_autotune_way_e state) +{ + pid_autotune_hd->autotune_way = state; +} + +/*整定过程中判断阀门状态:移动、停止、停止但仍在等待*/ +static valve_position_change_e pwmp_adjust_hd_valve_position_change(uint8_t *state, uint8_t next_state, uint8_t diff_adc_max) +{ + uint16_t diff_adc = 0; + // uint16_t adc = get_actual_travel_adc(); + uint16_t adc = get_actual_travel_adc(); + pid_autotune_hd->data.adjust_tmp_actual = adc; + + if (mode_pwmp_hd_adjust->psb_adc != adc) + { + diff_adc = ABS(mode_pwmp_hd_adjust->psb_adc - adc); + } + + if (diff_adc > diff_adc_max) + { + // 位置还在改变,继续等待 + mode_pwmp_hd_adjust->psb_adc = adc; + return POSITION_CHANGE; + } + else + { + // 位置不变 + if (mode_pwmp_hd_adjust->wait_count == 0) + { + // 等待次数也到了,位置不再发生变化,可以切换下一个状态 + *state = next_state; + return POSITION_NO_CHANGE_FOREVER; + } + else + { // 当位置不变的时候才开始等待 + mode_pwmp_hd_adjust->wait_count--; + return POSITION_NO_CHANGE; + } + } +} + +/*获得切线的横坐标(时间) +输入:actual_in为纵坐标,表示阀位的行程 +*/ +static float32 get_time_tangent(float actual_in) +{ + return (actual_in - pid_autotune_hd->data.b) / pid_autotune_hd->data.k; +} + +//////////////////////////////*整定相关函数END*///////////////////////////////////////////////////////// + +//////////////////////////////////*状态机模式BEGIN*///////////////////////////////////////////////////// +/*整定等待状态*/ +static void pwmp_adjust_hd_idle(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + if (!FSM_IS_WAIT(*state)) + { + sys_millis_reset(); + osel_memset((uint8_t *)&mode_pwmp_hd->pwmp_save->storage, 0, sizeof(mode_pwmp_hd_storage_data_t)); + mode_pwmp_hd->pwmp_save->storage.tuned_flag = TUNED_ONGOING; + /*为指针开辟存储空间*/ + if (mode_pwmp_hd_adjust == NULL) + { + mode_pwmp_hd_adjust = osel_mem_alloc(sizeof(pwmp_hd_adjust_t)); + DBG_ASSERT(mode_pwmp_hd_adjust != NULL __DBG_LINE); + } + osel_memset((uint8_t *)mode_pwmp_hd_adjust, 0, sizeof(pwmp_hd_adjust_t)); + + if (pid_autotune_hd == NULL) + { + pid_autotune_hd = (pid_autotune_hd_t *)osel_mem_alloc(sizeof(pid_autotune_hd_t)); + } + osel_memset((uint8_t *)pid_autotune_hd, 0, sizeof(pid_autotune_hd_t)); + + /*输出初始化*/ + mode_pwmp_hd_adjust->arr_default = mode_pwmp_hd->arr_default; + mode_pwmp_hd_adjust->arr_current = 0; + + mode_pwmp_hd_adjust->adjust_state = (mode_pwmp_hd_adjust_state_e)*state; + FSM_WAIT(mode_pwmp_hd_adjust->adjust_state); // 等放气完毕就可以切入到else里面了 + *state = PWMP_HD_ADJUST_BLEEDING; + } + else + { + valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, next_state, DIFF_ADC); + + switch (s) + { + case POSITION_NO_CHANGE_FOREVER: + // 位置不再改变,记录此时阀门位置AD值 + mode_pwmp_hd_adjust->adc_record_1 = pid_autotune_hd->data.adjust_tmp_actual; + mode_pwmp_hd_adjust->adc_record_0 = pid_autotune_hd->data.adjust_tmp_actual; + break; + case POSITION_CHANGE: + *state = PWMP_HD_ADJUST_IDEL; + // 将等待时间设置为1s + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 10; + break; + default: + break; + } + } +} + +/*整定粗调0*/ +static void pwmp_adjust_hd_rough_position0(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + mode_pwmp_hd_adjust->psb_adc = get_actual_travel_adc(); + uint16_t current_adc = 0; + if (!FSM_IS_WAIT(*state)) + { + // 以10%增加,提高DAC输出,找到能推动阀门的最小值 + mode_pwmp_hd_adjust->arr_current = 100; + mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 20; + mode_pwmp_hd_adjust->adjust_state = (mode_pwmp_hd_adjust_state_e)*state; + FSM_WAIT(*state); // 设置等待状态 + } + else + { + valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, next_state, DIFF_ADC); + + current_adc = pid_autotune_hd->data.adjust_tmp_actual; + // 3.28修改:将DIFF_ADC_MAX由10改为6 + if (ABS(current_adc - mode_pwmp_hd_adjust->adc_record_1) >= 20U) // 阀位发生改变 + { + if (mode_pwmp_hd_adjust->arr_last > 4000) + { + // 整定失败:位置反馈错误 + *state = PWMP_HD_ADJUST_FAIL; + } + else + { + /*得到一个粗略的,小于启动量的值*/ + mode_pwmp_hd_adjust->arr_record_1 = mode_pwmp_hd_adjust->arr_last > 1000 ? mode_pwmp_hd_adjust->arr_last * 0.9 : mode_pwmp_hd_adjust->arr_last; + /*判断位置反馈磁条是正装还是反装*/ + mode_pwmp_hd_adjust->adc_0_100_flag = mode_pwmp_hd_adjust->adc_record_0 < current_adc ? TRUE : FALSE; + } + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; + *state = next_state; + } + else // 阀位未发生变化:继续增大输出 + { + switch (s) + { + case POSITION_NO_CHANGE_FOREVER: // 位置不再改变 + { + + if (ABS(current_adc - mode_pwmp_hd_adjust->adc_record_1) <= DIFF_ADC) + { + // 没有发生变化 + mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; + if (mode_pwmp_hd_adjust->arr_last < 500) + { + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_current * 1.05; + } + else + { + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_current * 1.02; + } + /*若输出信号为最大值时认定为整定错误*/ + if (mode_pwmp_hd_adjust->arr_current > 4000) + { + // 整定失败:位置反馈错误 + *state = PWMP_HD_ADJUST_FAIL; + return; + } + + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 40; + *state = PWMP_HD_ADJUST_ROUGH_POSITION0; + FSM_WAIT(*state); // 设置等待状态 + } + else + { + DBG_ASSERT(FALSE __DBG_LINE); + } + break; + } + case POSITION_CHANGE: + DBG_ASSERT(FALSE __DBG_LINE); + break; + case POSITION_NO_CHANGE: + { + break; + } + default: + break; + } + } + } +} + +/*放气值(0信号)的整定*/ +static void pwmp_adjust_hd_bleeding_position0(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + BOOL flag = FALSE; + mode_pwmp_hd_adjust->psb_adc = get_actual_travel_adc(); + if (!FSM_IS_WAIT(*state)) + { + if (mode_pwmp_hd_adjust->wait_count-- > 0) + { + // 等待放气完毕 + return; + } + mode_pwmp_hd_adjust->flag_stable_begin = TRUE; + mode_pwmp_hd_adjust->flag_stable_end = FALSE; + mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->last_adc = mode_pwmp_hd_adjust->psb_adc; + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 20; + FSM_WAIT(*state); // 设置等待状态 + } + else + { + // if (mode_pwmp_hd_adjust->adc_0_100_flag) + // { + // if (mode_pwmp_hd_adjust->psb_adc <= mode_pwmp_hd_adjust->last_adc) + // { + // if (ABS(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->last_adc) > DIFF_ADC) + // { + // mode_pwmp_hd_adjust->arr_record_0 = mode_pwmp_hd_adjust->arr_last + DIFF_ADC; + // flag = TRUE; + // } + // } + // } + // else + // { + // if (mode_pwmp_hd_adjust->psb_adc >= mode_pwmp_hd_adjust->last_adc) + // { + // if (ABS(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->last_adc) > DIFF_ADC) + // { + // mode_pwmp_hd_adjust->arr_record_0 = mode_pwmp_hd_adjust->arr_last + DIFF_ADC; + // flag = TRUE; + // } + // } + // } + + /*求出阀位稳定信号*/ + // 阀位变化小于3且不为初始阀位附近时认定进入阀位稳定区域 + if (abs(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->last_adc) < 2 && abs(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->adc_record_1) > 50) + { + if (mode_pwmp_hd_adjust->flag_stable_begin) + { + mode_pwmp_hd_adjust->arr_record_stable_begin = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->flag_stable_begin = FALSE; + mode_pwmp_hd_adjust->flag_stable_end = TRUE; + } + } + + if (mode_pwmp_hd_adjust->adc_0_100_flag) // adc_0_100_flag true:ad值增大 false:ad值减小 + { + if (mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->last_adc < -DIFF_ADC && mode_pwmp_hd_adjust->flag_stable_end) + { + mode_pwmp_hd_adjust->flag_stable_end = FALSE; + // 阀位回落 + mode_pwmp_hd_adjust->arr_record_stable_end = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->arr_record_stable = (mode_pwmp_hd_adjust->arr_record_stable_begin + mode_pwmp_hd_adjust->arr_record_stable_end) / 2; + } + } + else + { + if (mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->last_adc > DIFF_ADC && mode_pwmp_hd_adjust->flag_stable_end) + { + mode_pwmp_hd_adjust->flag_stable_end = FALSE; + // 阀位回落 + mode_pwmp_hd_adjust->arr_record_stable_end = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->arr_record_stable = (mode_pwmp_hd_adjust->arr_record_stable_begin + mode_pwmp_hd_adjust->arr_record_stable_end) / 2; + } + } + + // 判断阀位是否回落到底部位置 + if (ABS(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->adc_record_1) < 6) + { + mode_pwmp_hd_adjust->arr_record_0 = mode_pwmp_hd_adjust->arr_current; + flag = TRUE; + } + + if (flag == TRUE) + { + mode_pwmp_hd_adjust->arr_record_2 = 4095; // 给定最大值输出 + *state = next_state; + pdctrl_out(0); // 这里要先放气5秒然后计算全开时间 + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; + } + else + { + mode_pwmp_hd_adjust->wait_count--; + if (flag == FALSE && mode_pwmp_hd_adjust->wait_count == 0) + { + uint16_t last = mode_pwmp_hd_adjust->arr_last; + mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->arr_current = last - 4; + + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + if (ABS(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->last_adc) > 6) + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 10; + } + else + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 30; + } + + mode_pwmp_hd_adjust->last_adc = mode_pwmp_hd_adjust->psb_adc; + } + } + } +} + +// /*启动值细调*/ +// static void pwmp_adjust_hd_accurate_position0(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +// { +// uint16_t current_adc = 0; +// if (!FSM_IS_WAIT(*state)) +// { +// mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_record_1; +// mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; +// mode_pwmp_hd_adjust->adjust_state = (mode_pwmp_hd_adjust_state_e)*state; +// FSM_WAIT(mode_pwmp_hd_adjust->adjust_state); +// *state = PWMP_HD_ADJUST_BLEEDING; +// } +// else +// { +// valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, next_state, DIFF_ADC); + +// current_adc = pid_autotune_hd->data.adjust_tmp_actual; +// /*执行器发生动作*/ +// if (ABS(current_adc - mode_pwmp_hd_adjust->adc_record_1) >= DIFF_ADC) +// { +// mode_pwmp_hd_adjust->arr_record_1 = mode_pwmp_hd_adjust->arr_last; +// mode_pwmp_hd_adjust->arr_record_2 = 4095; // 给定最大值输出 +// *state = next_state; +// pdctrl_out(0); // 这里要先放气5秒然后计算全开时间 +// mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; +// } +// else +// { +// switch (s) +// { +// case POSITION_NO_CHANGE_FOREVER: // 位置不再改变 +// { +// /*若执行器在0位置*/ +// if (ABS(current_adc - mode_pwmp_hd_adjust->adc_record_1) <= DIFF_ADC) +// { +// // 阀位没有发生变化,以每6增大信号输出 +// mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; +// mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_current + 6; +// pdctrl_out(mode_pwmp_hd_adjust->arr_current); +// mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 30; +// *state = PWMP_HD_ADJUST_ACCURATE_POSITION0; +// FSM_WAIT(*state); // 设置等待状态 +// } +// else +// { +// DBG_ASSERT(FALSE __DBG_LINE); +// } +// break; +// } +// case POSITION_CHANGE: +// DBG_ASSERT(FALSE __DBG_LINE); +// break; +// default: +// break; +// } +// } +// } +// } + +/*粗略整定得到满位置adc位置反馈*/ +static void pwmp_adjust_hd_rough_position100(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + uint16_t current_adc = 0; + // 找最大推动值arr + if (!FSM_IS_WAIT(*state)) + { + /*上一步赋值的count*/ + if (mode_pwmp_hd_adjust->wait_count-- > 0) + { + // 等待放气完毕 + return; + } + + sys_millis_reset(); + mode_pwmp_hd_adjust->all_open_time_full = sys_millis(); // 记录全开起始时间 + mode_pwmp_hd_adjust->tmp_time = 0; + + pdctrl_out(mode_pwmp_hd_adjust->arr_record_2); // 以最大值进行输出 + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; // 等待时间设置为5s + mode_pwmp_hd_adjust->adjust_state = (mode_pwmp_hd_adjust_state_e)*state; + FSM_WAIT(*state); // 设置等待状态 + } + else + { + valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, next_state, DIFF_ADC); + current_adc = pid_autotune_hd->data.adjust_tmp_actual; + + switch (s) + { + case POSITION_NO_CHANGE_FOREVER: + // 位置不再改变,记录此时阀门位置AD值 + mode_pwmp_hd_adjust->adc_record_2 = current_adc; + mode_pwmp_hd_adjust->all_open_time_full = mode_pwmp_hd_adjust->tmp_time - mode_pwmp_hd_adjust->all_open_time_full; + break; + case POSITION_CHANGE: + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; + mode_pwmp_hd_adjust->tmp_time = 0; + break; + case POSITION_NO_CHANGE: + if (mode_pwmp_hd_adjust->tmp_time == 0) + { + mode_pwmp_hd_adjust->tmp_time = sys_millis(); + } + break; + default: + break; + } + } +} + +/*精调冲顶值*/ +static void pwmp_adjust_hd_accurate_position100(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_adjust->all_close_time_flag = TRUE; + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_record_1; // 初始值为前一步整定出的最小启动值 + mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->adjust_state = (mode_pwmp_hd_adjust_state_e)*state; + mode_pwmp_hd_adjust->preheat = TRUE; + FSM_WAIT(mode_pwmp_hd_adjust->adjust_state); // 等放气完毕就可以切入到else里面了 + *state = PWMP_HD_ADJUST_BLEEDING; + } + else + { + valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, next_state, DIFF_ADC); + mode_pwmp_hd_adjust->psb_adc = pid_autotune_hd->data.adjust_tmp_actual; + + /*当前反馈AD值与最大位置AD值的差值*/ + uint16_t adc_diff = ABS(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->adc_record_2); + + if (mode_pwmp_hd_adjust->arr_current == 0 && mode_pwmp_hd_adjust->preheat == TRUE) + { + // 放气完毕会进入到这里 + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_record_1 + 20; + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 30; + return; + } + + switch (s) + { + case POSITION_NO_CHANGE_FOREVER: // 位置不再改变 + { + if (adc_diff <= 10) + { + *state = next_state; + mode_pwmp_hd_adjust->arr_record_2 = mode_pwmp_hd_adjust->arr_current; + } + else + { + uint8_t offset = 0; + + /*每次增大的信号值*/ + offset = 3; + + /*若快到顶时等待10s,否则等待1s*/ + if (adc_diff < 20) + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 100; + } + else + { + /*40mm————30;16mm————40*/ + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 30; + } + mode_pwmp_hd_adjust->last_adc = mode_pwmp_hd_adjust->psb_adc; + mode_pwmp_hd_adjust->arr_last = mode_pwmp_hd_adjust->arr_current; + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_current + offset; + + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + *state = PWMP_HD_ADJUST_ACCURATE_POSITION100; + FSM_WAIT(*state); // 设置等待状态 + } + + break; + } + case POSITION_CHANGE: + if (adc_diff < 20) + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 100; + } + else + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 20; + } + + break; + default: + break; + } + } +} + +/*计算控制的全关时间:以ATO类型角度命名*/ +static void pwmp_adjust_hd_all_close_time(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_record_0 - 100; // 此处的输入信号大小根据实际控制的最小值来设定 + + /*记录起始的全开时间*/ + sys_millis_reset(); + mode_pwmp_hd_adjust->all_close_time = sys_millis(); + mode_pwmp_hd_adjust->tmp_time = 0; + + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + mode_pwmp_hd_adjust->psb_adc = get_actual_travel_adc(); + if (abs(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->adc_record_0) < DIFF_ADC) + { + if (udevice.value_action_type == ATO) // 若调节阀为气开阀 + { + mode_pwmp_hd_adjust->tmp_time = sys_millis(); + mode_pwmp_hd_adjust->all_close_time = mode_pwmp_hd_adjust->tmp_time - mode_pwmp_hd_adjust->all_close_time; + } + else // 若调节阀为气关阀 + { + mode_pwmp_hd_adjust->tmp_time = sys_millis(); + mode_pwmp_hd_adjust->all_open_time = mode_pwmp_hd_adjust->tmp_time - mode_pwmp_hd_adjust->all_close_time; + } + *state = next_state; + } + } +} + +/*计算控制的全开时间*/ +static void pwmp_adjust_hd_all_open_time(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_record_2 + 100; // 此处的输入信号大小根据实际控制的最大值来设定 + + /*记录起始的全开时间*/ + sys_millis_reset(); + mode_pwmp_hd_adjust->all_open_time = sys_millis(); + mode_pwmp_hd_adjust->tmp_time = 0; + + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + mode_pwmp_hd_adjust->psb_adc = get_actual_travel_adc(); + if (abs(mode_pwmp_hd_adjust->psb_adc - mode_pwmp_hd_adjust->adc_record_2) < DIFF_ADC) + { + if (udevice.value_action_type == ATO) + { + mode_pwmp_hd_adjust->tmp_time = sys_millis(); + mode_pwmp_hd_adjust->all_open_time = mode_pwmp_hd_adjust->tmp_time - mode_pwmp_hd_adjust->all_open_time; + } + else + { + mode_pwmp_hd_adjust->tmp_time = sys_millis(); + mode_pwmp_hd_adjust->all_close_time = mode_pwmp_hd_adjust->tmp_time - mode_pwmp_hd_adjust->all_open_time; + } + *state = next_state; + } + } +} + +/*计算阀门自整定参数*/ +static void pwmp_adjust_hd_calculate(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + if (!FSM_IS_WAIT(*state)) + { + /*行程上下限*/ + mode_pwmp_hd->pwmp_save->storage.trip_0 = mode_pwmp_hd_adjust->adc_record_0; + mode_pwmp_hd->pwmp_save->storage.trip_100 = mode_pwmp_hd_adjust->adc_record_2; + mode_pwmp_hd->pwmp_save->storage.ad_diff = ABS(mode_pwmp_hd->pwmp_save->storage.trip_0 - mode_pwmp_hd->pwmp_save->storage.trip_100); + + /*控制区间*/ + mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin = mode_pwmp_hd_adjust->arr_record_2; + mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin = mode_pwmp_hd_adjust->arr_record_0; + mode_pwmp_hd->pwmp_save->storage.arr_diff = ABS(mode_pwmp_hd_adjust->arr_record_2 - mode_pwmp_hd_adjust->arr_record_0); + mode_pwmp_hd->pwmp_save->storage.pwmp_max = mode_pwmp_hd_adjust->arr_record_2 + (mode_pwmp_hd->pwmp_save->storage.arr_diff); + mode_pwmp_hd->pwmp_save->storage.pwmp_min = mode_pwmp_hd_adjust->arr_record_0 - (mode_pwmp_hd->pwmp_save->storage.arr_diff); + + /*启动值*/ + mode_pwmp_hd->pwmp_save->storage.startup_value = mode_pwmp_hd_adjust->adc_record_1; + + /*全开及全关时间*/ + mode_pwmp_hd->pwmp_save->storage.all_open_time = mode_pwmp_hd_adjust->all_open_time; + mode_pwmp_hd->pwmp_save->storage.all_close_time = mode_pwmp_hd_adjust->all_close_time; + mode_pwmp_hd->pwmp_save->storage.all_open_time_full = mode_pwmp_hd_adjust->all_open_time_full; + /*判断调节阀类型(气开/气关),对最低行程和最高行程进行标定*/ + if (udevice.value_action_type == ATO) + { + mode_pwmp_hd->pwmp_save->storage.trip_100 = mode_pwmp_hd->pwmp_save->storage.trip_100; + mode_pwmp_hd->pwmp_save->storage.trip_0 = mode_pwmp_hd->pwmp_save->storage.trip_0; + } + else + { + uint16_t tmp = mode_pwmp_hd->pwmp_save->storage.trip_100; + mode_pwmp_hd->pwmp_save->storage.trip_100 = mode_pwmp_hd->pwmp_save->storage.trip_0; + mode_pwmp_hd->pwmp_save->storage.trip_0 = tmp; + } + + // 保存安装方向 + if (mode_pwmp_hd->pwmp_save->storage.trip_100 > mode_pwmp_hd->pwmp_save->storage.trip_0) // 上大下小,正装 + { + udevice.dev_install_dir = 1; + } + else // 充气,ADC减小,正装 + { + udevice.dev_install_dir = 0; + } + + udevice.pos0_travel_vol = mode_pwmp_hd->pwmp_save->storage.trip_0; + udevice.pos100_travel_vol = mode_pwmp_hd->pwmp_save->storage.trip_100; + udevice.output_min = mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin; + udevice.output_max = mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin; + calib_parapos_perent(); + + mode_pwmp_hd_adjust->adjust_state = (mode_pwmp_hd_adjust_state_e)*state; + FSM_WAIT(mode_pwmp_hd_adjust->adjust_state); // 等放气完毕就可以切入到else里面了 + *state = PWMP_HD_ADJUST_BLEEDING; + } + else + { + *state = next_state; + } +} +/*排气状态*/ +static void pwmp_adjust_hd_bleeding(uint8_t *state) +{ + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_adjust->arr_current = mode_pwmp_hd_adjust->arr_default; + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 80; + pdctrl_out(0); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, mode_pwmp_hd_adjust->adjust_state, DIFF_ADC); + mode_pwmp_hd_adjust->psb_adc = mode_pwmp_hd_adjust->psb_adc; + switch (s) + { + case POSITION_NO_CHANGE_FOREVER: + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; // 排气状态结束后在跳转后的状态中等待5s + mode_pwmp_hd_adjust->arr_current = 0; + // if (mode_pwmp_hd_adjust->psb_adc != mode_pwmp_hd_adjust->adc_record_1) + // { + // mode_pwmp_hd_adjust->adc_record_1 = mode_pwmp_hd_adjust->psb_adc; + // mode_pwmp_hd->pwmp_save->storage.trip_0 = mode_pwmp_hd_adjust->psb_adc; + // } + break; + case POSITION_CHANGE: + if (mode_pwmp_hd_adjust->adc_record_0 == 0) + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 80; + } + else + { + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 50; + } + mode_pwmp_hd_adjust->tmp_time = 0; + break; + case POSITION_NO_CHANGE: + break; + default: + *state = PWMP_HD_ADJUST_STOP; + break; + } + } +} + +/*停止模式*/ +static void pwmp_adjust_hd_stop(uint8_t *state) +{ + if (mode_pwmp_hd_adjust != NULL) + { + osel_mem_free(mode_pwmp_hd_adjust); + mode_pwmp_hd_adjust = NULL; + } + *state = PWMP_HD_ADJUST_IDEL; + if (mode_pwmp_hd->auto_tune_state == PWMP_HD_ADJUST_RESULT_TUNING) + { + mode_pwmp_hd->auto_tune_state = PWMP_HD_ADJUST_RESULT_IDEL; + } + // 整定结束,将模式设置为控制模式 + pwmp_hd_process_state_set(PWMP_HD_PROCESS_CONTROL); +} + +/*整定错误状态*/ +static void pwmp_adjust_hd_fail(uint8_t *state) +{ + if (mode_pwmp_hd_adjust->arr_record_1 == 0) + { + // 阀位反馈错误 + } + // 反馈结果(整定错误) + mode_pwmp_hd->auto_tune_state = PWMP_HD_ADJUST_RESULT_FAIL; +} + +/*PID参数整定模式*/ +// 通过整定获得K、T、L(tao) +int s_watch; +static void pwmp_adjust_hd_PID_tuning(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + if (!FSM_IS_WAIT(*state)) + { + /*记录运行时间*/ + sys_millis_reset(); + pid_autotune_hd->data.pid_autotune_time_origin = sys_millis(); // 记录整定起始时间 + mode_pwmp_hd_adjust->tmp_time = 0; + /*整定方法选择*/ + pid_autotune_way_set(PID_AUTOTUNE_WAY_ZN); + /*阶跃信号设置*/ + pid_autotune_hd->data.step_signal = mode_pwmp_hd_adjust->arr_record_2; + pdctrl_out(pid_autotune_hd->data.step_signal); + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 40; // 等待四秒 + FSM_WAIT(*state); // 设置等待状态 + } + else + { + valve_position_change_e s = pwmp_adjust_hd_valve_position_change(state, next_state, DIFF_ADC); + s_watch = s; + /*获取实时行程*/ + pid_autotune_hd->data.cur_actual = pid_autotune_hd->data.adjust_tmp_actual; + /*计算变化率*/ + pid_autotune_hd->data.actual_error = pid_autotune_hd->data.cur_actual - pid_autotune_hd->data.pre_actual; + if (pid_autotune_hd->data.actual_error > 1000) + { + pid_autotune_hd->data.slope = 0; + } + else + { + pid_autotune_hd->data.slope = pid_autotune_hd->data.actual_error / TIME_CYCLE; + } + /*记录下变化率最大点值及行程坐标、时间*/ + if (pid_autotune_hd->data.slope > pid_autotune_hd->data.slope_Max) + { + pid_autotune_hd->data.slope_Max = pid_autotune_hd->data.slope; + pid_autotune_hd->data.actual_slope_Max = pid_autotune_hd->data.cur_actual; + mode_pwmp_hd_adjust->tmp_time = sys_millis(); + pid_autotune_hd->data.time_slope_Max = mode_pwmp_hd_adjust->tmp_time - pid_autotune_hd->data.pid_autotune_time_origin; + } + /*保存前一次的行程*/ + pid_autotune_hd->data.pre_actual = pid_autotune_hd->data.cur_actual; + /*只有当阀位大于前端*/ + if (pid_autotune_hd->data.cur_actual > 2) + { + switch (s) + { + case POSITION_NO_CHANGE_FOREVER: + /*获取稳定时的行程*/ + pid_autotune_hd->data.actual_stable = pid_autotune_hd->data.cur_actual; + /*计算切线的k和b*/ + pid_autotune_hd->data.k = pid_autotune_hd->data.slope_Max; + pid_autotune_hd->data.b = pid_autotune_hd->data.actual_slope_Max - (pid_autotune_hd->data.k * pid_autotune_hd->data.time_slope_Max); + /*求得滞后时间L*/ + pid_autotune_hd->l_hd = get_time_tangent(0); + /*求得时间系数T*/ + pid_autotune_hd->t_hd = get_time_tangent(pid_autotune_hd->data.actual_stable) - pid_autotune_hd->l_hd; + /*K的计算*/ + pid_autotune_hd->k_hd = ((pid_autotune_hd->data.actual_stable) / (mode_pwmp_hd_adjust->adc_record_2 - mode_pwmp_hd_adjust->adc_record_0)) / ((pid_autotune_hd->data.step_signal) / (mode_pwmp_hd_adjust->arr_record_2 - mode_pwmp_hd_adjust->arr_record_0)); + + *state = next_state; + break; + case POSITION_CHANGE: + mode_pwmp_hd_adjust->wait_count = mode_pwmp_hd->wait_count_max * 40; + break; + case POSITION_NO_CHANGE: + break; + default: + *state = PWMP_HD_ADJUST_STOP; + break; + } + } + } +} + +/*参数计算模式*/ +static void pwmp_adjust_hd_pid_calculate(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + switch (pid_autotune_hd->autotune_way) + { + case PID_AUTOTUNE_WAY_ZN: + if ((pid_autotune_hd->l_hd / pid_autotune_hd->t_hd) <= 0.2) + { + pid_autotune_hd->p_auto_hd = (pid_autotune_hd->t_hd / (0.85 * pid_autotune_hd->l_hd * pid_autotune_hd->k_hd)); + pid_autotune_hd->ti_auto_hd = 2 * pid_autotune_hd->l_hd; + pid_autotune_hd->td_auto_hd = 0.5 * pid_autotune_hd->l_hd; + } + else if ((pid_autotune_hd->l_hd / pid_autotune_hd->t_hd) > 0.2) + { + pid_autotune_hd->p_auto_hd = ((1 / pid_autotune_hd->k_hd) * (pid_autotune_hd->l_hd / pid_autotune_hd->t_hd) + 0.6) / (2.6 * (pid_autotune_hd->l_hd / pid_autotune_hd->t_hd) - 0.08); + pid_autotune_hd->ti_auto_hd = 0.18 * pid_autotune_hd->t_hd + 0.19 * pid_autotune_hd->l_hd; + pid_autotune_hd->td_auto_hd = 0.25 * pid_autotune_hd->ti_auto_hd; + } + pid_autotune_hd->i_auto_hd = pid_autotune_hd->p_auto_hd / pid_autotune_hd->ti_auto_hd; + pid_autotune_hd->d_auto_hd = (pid_autotune_hd->td_auto_hd * pid_autotune_hd->p_auto_hd) / pid_autotune_hd->t_hd; + break; + case PID_AUTOTUNE_WAY_CC: + /*Kp、Ti、Td的求取*/ + pid_autotune_hd->p_auto_hd = ((pid_autotune_hd->t_hd / (pid_autotune_hd->k_hd * pid_autotune_hd->l_hd)) * (4 / 3 + (pid_autotune_hd->l_hd / (pid_autotune_hd->t_hd * 4)))); + pid_autotune_hd->ti_auto_hd = pid_autotune_hd->l_hd * ((32 + 6 * (pid_autotune_hd->l_hd / pid_autotune_hd->t_hd)) / (13 + 8 * (pid_autotune_hd->l_hd / pid_autotune_hd->l_hd))); + pid_autotune_hd->td_auto_hd = (4 * pid_autotune_hd->l_hd) / (11 + 2 * (pid_autotune_hd->l_hd / pid_autotune_hd->t_hd)); + /*Ki、Kd的求取*/ + pid_autotune_hd->i_auto_hd = pid_autotune_hd->p_auto_hd / pid_autotune_hd->ti_auto_hd; + pid_autotune_hd->d_auto_hd = (pid_autotune_hd->td_auto_hd * pid_autotune_hd->p_auto_hd) / pid_autotune_hd->t_hd; + break; + default: + break; + } + mode_pwmp_hd->pwmp_save->storage.kp = fabs(pid_autotune_hd->p_auto_hd); + mode_pwmp_hd->pwmp_save->storage.ki = fabs(pid_autotune_hd->i_auto_hd); + mode_pwmp_hd->pwmp_save->storage.kd = fabs(pid_autotune_hd->d_auto_hd); + *state = next_state; // 将状态切换 +} + +/**/ + +/*参数保存模式*/ +static void pwmp_adjust_hd_save(uint8_t *state, mode_pwmp_hd_adjust_state_e next_state) +{ + *state = next_state; + if (mode_pwmp_hd->pwmp_save->storage.tuned_flag == TUNED_ONGOING) + { + mode_pwmp_hd->pwmp_save->storage.tuned_flag = TUNED_SUCCESS; + mode_pwmp_hd->auto_tune_state = PWMP_HD_ADJUST_RESULT_SUCCESS; + pwmp_public_params_update(); + } + else + { + mode_pwmp_hd->pwmp_save->storage.tuned_flag = TUNED_FAILED; + } + mode_pwmp_hd->params_save_cb(); +} + +//////////////////////////////////*状态机模式END*////////////////////////////////////////////////////// + +//////////////////////////////*整定程序入口BEGIN*////////////////////////////////////////////////////// + +void pwmp_adjust(uint8_t *state) +{ + uint8_t ts = *state; + BIT_CLR(ts, BIT7); // 高位清零 + switch (ts) + { + case PWMP_HD_ADJUST_ROUGH_POSITION0: + pwmp_adjust_hd_rough_position0(state, PWMP_HD_ADJUST_BLEEDING_POSITION0); + break; + case PWMP_HD_ADJUST_BLEEDING_POSITION0: + pwmp_adjust_hd_bleeding_position0(state, PWMP_HD_ADJUST_ROUGH_POSITION100); + break; + case PWMP_HD_ADJUST_ROUGH_POSITION100: + pwmp_adjust_hd_rough_position100(state, PWMP_HD_ADJUST_ACCURATE_POSITION100); + break; + case PWMP_HD_ADJUST_ACCURATE_POSITION100: + pwmp_adjust_hd_accurate_position100(state, PWMP_HD_ADJUST_ALL_CLOSE_TIME); + break; + case PWMP_HD_ADJUST_ALL_CLOSE_TIME: + pwmp_adjust_hd_all_close_time(state, PWMP_HD_ADJUST_ALL_OPEN_TIME); + break; + case PWMP_HD_ADJUST_ALL_OPEN_TIME: + pwmp_adjust_hd_all_open_time(state, PWMP_HD_ADJUST_CALCULATE); + break; + case PWMP_HD_ADJUST_CALCULATE: + pwmp_adjust_hd_calculate(state, PWMP_HD_ADJUST_PID_TUNING); + break; + case PWMP_HD_ADJUST_PID_TUNING: + pwmp_adjust_hd_PID_tuning(state, PWMP_HD_ADJUST_PID_CALCULATE); + break; + case PWMP_HD_ADJUST_PID_CALCULATE: + pwmp_adjust_hd_pid_calculate(state, PWMP_HD_ADJUST_SAVE); + break; + case PWMP_HD_ADJUST_SAVE: + pwmp_adjust_hd_save(state, PWMP_HD_ADJUST_STOP); + break; + case PWMP_HD_ADJUST_BLEEDING: + pwmp_adjust_hd_bleeding(state); + break; + case PWMP_HD_ADJUST_IDEL: + pwmp_adjust_hd_idle(state, PWMP_HD_ADJUST_ROUGH_POSITION0); + break; + case PWMP_HD_ADJUST_STOP: + pwmp_adjust_hd_stop(state); + break; + case PWMP_HD_ADJUST_FAIL: + pwmp_adjust_hd_fail(state); + pwmp_adjust_hd_stop(state); + break; + default: + pwmp_adjust_hd_stop(state); + break; + } + + switch (ts) + { + case PWMP_HD_ADJUST_IDEL: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_IDEL; + break; + case PWMP_HD_ADJUST_ROUGH_POSITION0: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_POSITION0; + break; + case PWMP_HD_ADJUST_ACCURATE_POSITION0: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_POSITION0; + break; + case PWMP_HD_ADJUST_ROUGH_POSITION100: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_POSITION100; + break; + case PWMP_HD_ADJUST_ACCURATE_POSITION100: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_POSITION100; + break; + case PWMP_HD_ADJUST_BLEEDING_TIMER: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_TIMER; + break; + case PWMP_HD_ADJUST_AERATE_TIMER: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_TIMER; + break; + case PWMP_HD_ADJUST_TUNING: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_TUNING; + break; + case PWMP_HD_ADJUST_SAVE: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_SAVE; + break; + case PWMP_HD_ADJUST_STOP: + mode_pwmp_hd->lcd_adjust_state = LCD_ADJUST_STOP; + break; + default: + break; + } +} +//////////////////////////////*整定程序入口END*////////////////////////////////////////////////////// + +//////////////////////////////*测试模式开始*/////////////////////////////////////////////////////////////////// +/*整定过程中判断阀门状态:移动、停止、停止但仍在等待*/ +/* +static valve_position_change_e pwmp_test_hd_valve_position_change(uint8_t *state, uint8_t next_state, uint8_t diff_adc_max) +{ + uint16_t diff_adc = 0; + uint16_t adc = mode_pwmp_hd_test->psb_adc; + + if (mode_pwmp_hd_test->psb_adc != adc) + { + diff_adc = ABS(mode_pwmp_hd_test->psb_adc - adc); + } + + if (diff_adc > diff_adc_max) + { + // 位置还在改变,继续等待 + mode_pwmp_hd_test->psb_adc = adc; + return POSITION_CHANGE; + } + else + { + // 位置不变 + if (mode_pwmp_hd_test->wait_count == 0) + { + // 等待次数也到了,位置不再发生变化,可以切换下一个状态 + *state = next_state; + return POSITION_NO_CHANGE_FOREVER; + } + else + { // 当位置不变的时候才开始等待 + mode_pwmp_hd_test->wait_count--; + return POSITION_NO_CHANGE; + } + } +} +*/ +static void pwmp_test_hd_velocity_test(uint8_t *state, mode_pwmp_hd_test_state_e next_state) +{ + pwmp_control_update(FILTER_AVERAGE); + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_test->arr_current = udevice.output_max; // 以最大的信号值输出 + pdctrl_out(mode_pwmp_hd_test->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + + if (abs(mode_pwmp_hd_test->psb_adc - udevice.pos0_travel_vol) < DIFF_ADC_MAX) + { + *state = next_state; + } + } +} +/*开环控制*/ +static void pwmp_test_hd_open_loop_output() +{ + pwmp_control_update(FILTER_AVERAGE); + pdctrl_out(mode_pwmp_hd->output); + mode_pwmp_hd->duty_percent = ((float32)mode_pwmp_hd->output / (float32)DAC_MAX) * 100; + mode_pwmp_hd->current_electric = ip2current(); +} + +/*采样得到小行程最大值*/ +static void pwmp_test_hd_get_small_travel_high(uint8_t *state, mode_pwmp_hd_test_small_travel_state_e next_state) +{ + pwmp_control_update(FILTER_AVERAGE); + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_test->arr_current = 4095; // 以最大的信号值输出 + pdctrl_out(mode_pwmp_hd_test->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + if (mode_pwmp_hd_test->small_trip_current_adc > mode_pwmp_hd_test->small_trip_adc_max) + { + mode_pwmp_hd_test->small_trip_adc_max = mode_pwmp_hd_test->small_trip_current_adc; + } + if (abs(mode_pwmp_hd_test->psb_adc - udevice.pos0_travel_vol) < DIFF_ADC_MAX) + { + *state = next_state; + } + } +} + +/*采样得到小行程最小值*/ +static void pwmp_test_hd_get_small_travel_low(uint8_t *state, mode_pwmp_hd_test_small_travel_state_e next_state) +{ + pwmp_control_update(FILTER_AVERAGE); + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_test->small_trip_adc_min = 4095; // 因为初始化将其赋值为0,为防止出现bug故将其初始化为4095 + mode_pwmp_hd_adjust->arr_current = 0; // 以最小的信号值输出 + pdctrl_out(mode_pwmp_hd_adjust->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + if (mode_pwmp_hd_test->small_trip_current_adc < mode_pwmp_hd_test->small_trip_adc_min) + { + mode_pwmp_hd_test->small_trip_adc_min = mode_pwmp_hd_test->small_trip_current_adc; + } + if (abs(mode_pwmp_hd_test->psb_adc - udevice.pos0_travel_vol) < DIFF_ADC_MAX) + { + *state = next_state; + } + } +} + +/*采样得到处于50%阀位时稳定的控制信号*/ +static void pwmp_test_hd_get_small_travel_50_per_arr(uint8_t *state, mode_pwmp_hd_test_small_travel_state_e next_state) +{ + execute_rsp_hd_t *execute_res; + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_test->ctrl_target = 50.0; // 将目标阀位设置为50% + mode_pwmp_hd_test->wait_count = 2000; // 等待20秒 + FSM_WAIT(*state); // 设置等待状态 + } + else + { + pwmp_control_update(FILTER_MEDIAN); + if (rt_data.loop_current >= 4.0) + { + execute_res = execute_dac(EXECUTE_PLAN); // PID计算结果经过执行器处理 + if (execute_res->code == EXECUTE_HD_OUT) // 执行DAC输出 + { + pdctrl_out(execute_res->dac); + } + } + /*当误差大于0.5%时重置等待时间*/ + if (fabs(mode_pwmp_hd_test->real_error) > 0.5) + { + mode_pwmp_hd_test->wait_count = 2000; + } + else + { + mode_pwmp_hd_test->wait_count--; + if (mode_pwmp_hd_test->wait_count == 0) + { + mode_pwmp_hd_test->arr_50_percent = execute_res->dac; + mode_pwmp_hd_test->small_trip_adc_50_percent = mode_pwmp_hd_test->small_trip_current_adc; + *state = next_state; + } + } + } +} + +/*得到小行程稳定区间上限*/ +static void pwmp_test_hd_get_small_travel_stable_range_up(uint8_t *state, mode_pwmp_hd_test_small_travel_state_e next_state) +{ + pwmp_control_update(FILTER_AVERAGE); + if (!FSM_IS_WAIT(*state)) + { + mode_pwmp_hd_test->wait_count = 400; // 等待8秒 + mode_pwmp_hd_test->ctrl_target = 50.0; // 将目标阀位设置为50% + mode_pwmp_hd_test->arr_current = mode_pwmp_hd_test->arr_50_percent; // 以50%阀位稳定信号值输出 + pdctrl_out(mode_pwmp_hd_test->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + if (fabs(mode_pwmp_hd_test->real_error) <= 0.5) + { + if (!(mode_pwmp_hd_test->wait_count--)) + { + mode_pwmp_hd_test->arr_current++; + mode_pwmp_hd_test->flag_stable = 1; + mode_pwmp_hd_test->wait_count = 400; + } + } + else + { + if (mode_pwmp_hd_test->flag_stable) + { + mode_pwmp_hd_test->small_trip_adc_stable_up = mode_pwmp_hd_test->small_trip_current_adc; + mode_pwmp_hd_test->wait_count = 800; // 等待8秒 + *state = next_state; + } + } + pdctrl_out(mode_pwmp_hd_test->arr_current); + } +} + +/*得到小行程稳定区间下限*/ +static void pwmp_test_hd_get_small_travel_stable_range_down(uint8_t *state, mode_pwmp_hd_test_small_travel_state_e next_state) +{ + pwmp_control_update(FILTER_AVERAGE); + if (!FSM_IS_WAIT(*state)) + { + /*等待上一次延时的时间*/ + if (mode_pwmp_hd_test->wait_count-- > 0) + { + return; + } + mode_pwmp_hd_test->wait_count = 400; // 等待4秒 + mode_pwmp_hd_test->ctrl_target = 50.0; // 将目标阀位设置为50% + mode_pwmp_hd_test->arr_current = mode_pwmp_hd_test->arr_50_percent; // 以50%阀位稳定信号值输出 + pdctrl_out(mode_pwmp_hd_test->arr_current); + FSM_WAIT(*state); // 设置等待状态 + } + else + { + if (fabs(mode_pwmp_hd_test->real_error) <= 0.5) + { + if (!(mode_pwmp_hd_test->wait_count--)) + { + mode_pwmp_hd_test->arr_current--; + mode_pwmp_hd_test->flag_stable = 1; + mode_pwmp_hd_test->wait_count = 400; + } + } + else + { + if (mode_pwmp_hd_test->flag_stable) + { + mode_pwmp_hd_test->small_trip_adc_stable_down = mode_pwmp_hd_test->small_trip_current_adc; + *state = next_state; + } + } + pdctrl_out(mode_pwmp_hd_test->arr_current); + } +} + +//////////////////////////////*测试模式结束*//////////////////////////////////////////////////////////////////////// + +//////////////////////////////*小回路测试模式入口*/////////////////////////////////////////////////////////////////// +void small_travel_test(uint8_t *state) +{ + uint8_t ts = *state; + BIT_CLR(ts, BIT7); // 高位清零 + switch (ts) + { + case PWMP_HD_TEST_GET_SMALL_TRAVEL_HIGH: + pwmp_test_hd_get_small_travel_high(state, PWMP_HD_TEST_GET_SMALL_TRAVEL_LOW); + break; + case PWMP_HD_TEST_GET_SMALL_TRAVEL_LOW: + pwmp_test_hd_get_small_travel_low(state, PWMP_HD_TEST_GET_SMALL_TRAVEL_50_PER_ARR); + break; + case PWMP_HD_TEST_GET_SMALL_TRAVEL_50_PER_ARR: + pwmp_test_hd_get_small_travel_50_per_arr(state, PWMP_HD_TEST_GET_SMALL_TRAVEL_STABLE_RANGE_UP); + break; + case PWMP_HD_TEST_GET_SMALL_TRAVEL_STABLE_RANGE_UP: + pwmp_test_hd_get_small_travel_stable_range_up(state, PWMP_HD_TEST_GET_SMALL_TRAVEL_STABLE_RANGE_DOWN); + break; + case PWMP_HD_TEST_GET_SMALL_TRAVEL_STABLE_RANGE_DOWN: + pwmp_test_hd_get_small_travel_stable_range_down(state, PWMP_HD_TEST_OPEN_LOOP_OUTPUT_TEST); + break; + case PWMP_HD_TEST_OPEN_LOOP_OUTPUT_TEST: + mode_pwmp_hd_test->test_state = PWMP_HD_TEST_OPEN_LOOP_OUTPUT; + break; + default: + mode_pwmp_hd_test->test_state = PWMP_HD_TEST_OPEN_LOOP_OUTPUT; + break; + } +} +/////////////////////////////*小回路测试模式出口*//////////////////////////////////////////////////////////////////// + +//////////////////////////////*测试模式入口BEGIN*/////////////////////////////////////////////////////////////////// +void pwmp_test(uint8_t *state) +{ + uint8_t ts = *state; + ts = PWMP_HD_TEST_OPEN_LOOP_OUTPUT; + BIT_CLR(ts, BIT7); // 高位清零 + switch (ts) + { + case VELOCITY_TEST: + pwmp_test_hd_velocity_test(state, SMALL_TRAVEL_TEST); + break; + case SMALL_TRAVEL_TEST: + small_travel_test((uint8_t *)&mode_pwmp_hd_test->small_travel_test_state); + case PWMP_HD_TEST_OPEN_LOOP_OUTPUT: + pwmp_test_hd_open_loop_output(); + break; + default: + pwmp_test_hd_open_loop_output(); + break; + } +} +//////////////////////////////*测试模式入口END*///////////////////////////////////////////////////////////////////// + +//////////////////////////////*入口BEGIN*////////////////////////////////////////////////////// +void mode_pwmp_hd_process(void) +{ + mode_pwmp_hd_control_t *p = &mode_pwmp_hd->control; + execute_rsp_hd_t *execute_res; + p->enter_count++; + if (p->enter_count % WAIT_COUNT_MAX == 0) // 100ms输出一次 + { + if (BIT_IS_SET(hc_24_state, BIT2)) + { + // 蓝牙输出 + char ble_data[128]; + uint8_t ble_len = 0; + osel_memset((uint8_t *)ble_data, 0, 128); + // sprintf(ble_data, "%f,%f,%f,%d,%f\r\n", pid_target, show_actual, p->real_error, mode_pwm->output, rt_data.loop_current ); + if (mode_pwmp_hd->process_state == PWMP_HD_PROCESS_TEST) + { + // sprintf(ble_data, "%f,%f,%f,%f\r\n", mode_pwmp_hd->control.ctrl_target, mode_pwmp_hd->control.ctrl_feedback, mode_pwmp_hd->control.real_error, rt_data.loop_current ); + if (mode_pwmp_hd_test->test_state == PWMP_HD_TEST_OPEN_LOOP_OUTPUT) + { + sprintf(ble_data, "%f,%d,%d,%f\r\n", mode_pwmp_hd->control.ctrl_feedback, mode_pwmp_hd_test->small_trip_current_adc, mode_pwmp_hd->output, mode_pwmp_hd->current_electric); + } + else + { + sprintf(ble_data, "%f,%f,%f,%d,%d\r\n", mode_pwmp_hd_test->ctrl_feedback, mode_pwmp_hd_test->ctrl_target, mode_pwmp_hd_test->real_error, mode_pwmp_hd_test->small_trip_current_adc, rsp.dac); + } + } + else if (mode_pwmp_hd->process_state == PWMP_HD_PROCESS_CONTROL || mode_pwmp_hd->process_state == PWMP_HD_PROCESS_STOP) + { + sprintf(ble_data, "%f,%f,%f,%d,%d\r\n", mode_pwmp_hd->control.ctrl_feedback, mode_pwmp_hd->control.ctrl_target, mode_pwmp_hd->control.real_error, mode_pwmp_hd->control.small_trip_current_adc, rsp.dac); + } + else if (mode_pwmp_hd->process_state == PWMP_HD_PROCESS_ADJUST) + { + sprintf(ble_data, "%d,%d\r\n", mode_pwmp_hd_adjust->psb_adc, mode_pwmp_hd_adjust->arr_current); + } + + ble_len = osel_mstrlen((unsigned char *)ble_data); + if (ble_len != 0) + { + h24_bluetooth_output_dbg((uint8_t *)ble_data, ble_len); + } + + // 蓝牙输出 + } + p->enter_count = 0; + } + + switch (mode_pwmp_hd->process_state) + { + case PWMP_HD_PROCESS_CONTROL: + { + pwmp_control_update(FILTER_MEDIAN); + if (rt_data.loop_current >= LOOP_CURRENT_MIN) + { + if (rt_data.loop_current < 4.5) + { + pdctrl_out(mode_pwmp_hd->pwmp_save->storage.pwmp_min_origin * 0.8); + } + else if (rt_data.loop_current > 19.5) + { + pdctrl_out(mode_pwmp_hd->pwmp_save->storage.pwmp_max_origin * 1.2); + } + else if (rt_data.loop_current >= 4.5 && rt_data.loop_current <= 19.5) + { + execute_res = execute_dac(EXECUTE_PLAN); // PID计算结果经过执行器处理 + if (execute_res->code == EXECUTE_HD_OUT) // 执行DAC输出 + { + pdctrl_out(execute_res->dac); + } + } + } + else + { + pdctrl_out(0); + } + break; + } + case PWMP_HD_PROCESS_ADJUST: + pwmp_adjust((uint8_t *)&mode_pwmp_hd->adjust_state); + break; + case PWMP_HD_PROCESS_STOP: + { + // TODO 完成停止自整定,并释放资源 + break; + } + case PWMP_HD_PROCESS_TEST: + { + pwmp_test((uint8_t *)&mode_pwmp_hd_test->test_state); + break; + } + default: + break; + } +} +//////////////////////////////*入口END*////////////////////////////////////////////////////// + +/*程序初始化*/ +void mode_pwmp_hd_init(mode_interface_req_t *req, uint16_t positioner_model, mode_pwmp_hd_params_u *params, void (*params_save_cb)(void)) +{ + DBG_ASSERT(req != NULL __DBG_LINE); + DBG_ASSERT(params != NULL __DBG_LINE); // 断言检查 + DBG_ASSERT(params_save_cb != NULL __DBG_LINE); + req->mode_process_start = _process_start; + req->mode_process_stop = _process_stop; + req->mode_adjust_start = _adjust_start; + req->mode_adjust_stop = _adjust_stop; + req->mode_get_adjust_data = _adjust_data; + req->mode_adjust_result = _adjust_result; + req->mode_adjust_step_count = _adjust_step_count; + req->mode_adjust_step_current = _adjust_step_current; + req->mode_control_idle = _control_idle; + req->mode_is_adjusting = _adjust_isrun; + + /*大电流输出使能开关*/ +#if VIP_H_EN_HD == 1 + VIP_H_EN_ENABLE(); +#endif + /*为指针开辟存储空间*/ + // 控制 + if (mode_pwmp_hd == NULL) + { + mode_pwmp_hd = (mode_pwmp_hd_t *)osel_mem_alloc(sizeof(mode_pwmp_hd_t)); + } + osel_memset((uint8_t *)mode_pwmp_hd, 0, sizeof(mode_pwmp_hd_t)); + // 整定 + if (mode_pwmp_hd_adjust == NULL) + { + mode_pwmp_hd_adjust = (pwmp_hd_adjust_t *)osel_mem_alloc(sizeof(pwmp_hd_adjust_t)); + } + osel_memset((uint8_t *)mode_pwmp_hd_adjust, 0, sizeof(pwmp_hd_adjust_t)); + // 调试 + if (mode_pwmp_hd_test == NULL) + { + mode_pwmp_hd_test = (pwmp_hd_test_t *)osel_mem_alloc(sizeof(pwmp_hd_test_t)); + } + osel_memset((uint8_t *)mode_pwmp_hd_test, 0, sizeof(pwmp_hd_test_t)); + /*滤波初始化*/ + mode_pwmp_hd->filter.handle = lpf_window_init(20); + /*绑定要保存的参数与函数*/ + mode_pwmp_hd->pwmp_save = params; + mode_pwmp_hd->params_save_cb = params_save_cb; + /*设定PWMP方式的工作模式*/ + pwmp_hd_process_state_set(PWMP_HD_PROCESS_CONTROL); + /*PID初始化*/ + execute_pid_init(EXECUTE_PLAN); + /*计数最大值*/ + mode_pwmp_hd->wait_count_max = 100 / ((MODE_DEFAULT_AUTOLOAD + 1) * 0.1); // (=10,每减一消耗10ms,总消耗时间100ms) + /*保存参数*/ + mode_pwmp_hd->params_save_cb(); + + /*更新公共参数*/ + pwmp_public_params_update(); + calib_parapos_perent(); +} diff --git a/User/application/mode/mode_pwmp_hd.h b/User/application/mode/mode_pwmp_hd.h new file mode 100644 index 0000000..c4c30c9 --- /dev/null +++ b/User/application/mode/mode_pwmp_hd.h @@ -0,0 +1,327 @@ +#ifndef __MODE_PWMP_HD_H__ +#define __MODE_PWMP_HD_H__ +#include "main.h" + +#define MODE_DEFAULT_AUTOLOAD 99 // 预分频系数 +#define WAIT_COUNT_MAX 10 // 蓝牙等待最大次数 + +#define VIP_H_EN_HD 1 // 高电压输出开关 +///////////////////////////////////////*算法整定部分宏定义BEGIN*//////////////////////////////////////// + +#define TIME_CYCLE 0.01f // 定义时间周期:10ms +#define FSM_WAIT(st) BIT_SET(st, BIT7) +#define FSM_IS_WAIT(st) (st & BIT7) +#define DIFF_ADC 10U +#define DIFF_ADC_MAX 6U + +///////////////////////////////////////*算法整定部分宏定义END*/////////////////////////////////////////// + +#define EXECUTE_PLAN EXECUTE_PLAN_1 + +/*----------------------------------------*/ +typedef enum +{ + PWMP_HD_PROCESS_CONTROL, + PWMP_HD_PROCESS_ADJUST, + PWMP_HD_PROCESS_ADJUST_STOP, + PWMP_HD_PROCESS_TEST, + PWMP_HD_PROCESS_STOP, +} mode_pwmp_hd_process_state_e; // 处理状态 + +/*需要存储的变量*/ +typedef struct +{ + uint8_t tuned_flag; // 整定标志 0:未整定,1:整定中,2:整定成功,3:整定失败 + uint16_t startup_value; // 阀位启动值 + uint16_t arr_diff; // 控制区间 + uint16_t ad_diff; // 磁条区间 + uint16_t pwmp_min; // 控制最小值 + uint16_t pwmp_max; // 控制最大值 + uint16_t pwmp_min_origin; // 整定控制最小值 + uint16_t pwmp_max_origin; // 整定控制最大值 + uint16_t trip_0; // 磁条0位置AD + uint16_t trip_100; // 词条100位置AD + uint16_t trip_min0; // 小回路行程0位置AD + uint16_t trip_min100; // 小回路行程100位置AD + uint16_t current0; // 电流最小值 + uint16_t current100; // 电流最大值 + uint16_t all_open_time; // 全开时间 + uint16_t all_close_time; // 全关时间 + uint16_t all_open_time_full; // 最大信号全开时间 + uint16_t prov_flag; // 磁条安装的正反:倒装:0 正装:1 + uint16_t valve_type; // 阀门正反行程:气开:ATO 气关:ATC + float32 kp; + float32 ki; + float32 kd; +} mode_pwmp_hd_storage_data_t; + +typedef struct +{ + __IO uint32_t enter_count; // 用于100ms蓝牙输出计时器 + float32 ctrl_target; // 目标值 + float32 ctrl_feedback; // 反馈值 + float32 real_error; // 实际误差 + uint16_t current_adc; // 当前ADC值 + uint16_t small_trip_current_adc; // 小行程反馈当前ADC值 +} mode_pwmp_hd_control_t; + +/*滤波处理*/ +typedef struct +{ + lpf_t actual_lpf; + lpf_t target_lpf; + lpf_window_t *handle; +} mode_pwmp_hd_filter_t; + +typedef union +{ + uint8_t data[128]; + // 自定义数据结构 + mode_pwmp_hd_storage_data_t storage; +} mode_pwmp_hd_params_u; + +typedef struct +{ + uint8_t lcd_adjust_state; // LCD自整定流程状态 + float32 duty_percent; // 占空比 + float32 current_electric; // 电流 + + uint8_t auto_tune_state; // 自整定状态 0:未整定 1:整定中 2:整定完成 3:整定失败 + uint16_t wait_count_max; // 等待次数最大值 + uint16_t arr_default; // 默认值array,推动值 + uint8_t process_state; // 处理状态 + uint8_t adjust_state; // 整定状态 + uint16_t output; // 输出值 + uint16_t current_adc; // 当前位置反馈的AD值 + uint32_t count; // 计数 + + mode_pwmp_hd_control_t control; + mode_pwmp_hd_filter_t filter; + mode_pwmp_hd_params_u *pwmp_save; + void (*params_save_cb)(void); +} mode_pwmp_hd_t; + +/////////////////////////////////////////*共用部分BEGIN*//////////////////////////////////////////////// +typedef enum +{ + VELOCITY_TEST, // 速度测试 + SMALL_TRAVEL_TEST, // 小回路测试 + PWMP_HD_TEST_OPEN_LOOP_OUTPUT, // 开环输出 +} mode_pwmp_hd_test_state_e; + +typedef enum +{ + PWMP_HD_TEST_GET_SMALL_TRAVEL_HIGH, // 获取小行程反馈的最大值 + PWMP_HD_TEST_GET_SMALL_TRAVEL_LOW, // 获取小行程反馈的最小值 + PWMP_HD_TEST_GET_SMALL_TRAVEL_50_PER_ARR, // 获取处于50%阀位时的控制值 + PWMP_HD_TEST_GET_SMALL_TRAVEL_STABLE_RANGE_UP, // 获取小行程反馈的稳定区间上限 + PWMP_HD_TEST_GET_SMALL_TRAVEL_STABLE_RANGE_DOWN, // 获取小行程反馈的稳定区间下限 + PWMP_HD_TEST_OPEN_LOOP_OUTPUT_TEST, +} mode_pwmp_hd_test_small_travel_state_e; + +typedef struct +{ + mode_pwmp_hd_test_state_e test_state; + mode_pwmp_hd_test_small_travel_state_e small_travel_test_state; + volatile uint16_t wait_count; + volatile uint16_t psb_adc; + volatile uint16_t last_adc; + + uint8_t flag_stable; // 稳定标志 + uint16_t small_trip_current_adc; // 小行程反馈当前值 + uint16_t small_trip_adc_max; // 小行程反馈最大值 + uint16_t small_trip_adc_min; // 小行程反馈最小值 + uint16_t small_trip_adc_stable_up; // 小行程反馈稳定区间上限值 + uint16_t small_trip_adc_stable_down; // 小行程反馈稳定区间下限值 + uint16_t small_trip_adc_50_percent; // 当阀位为50%时小行程反馈的adc值 + float32 ctrl_feedback; // 反馈值 + float32 ctrl_target; // 目标值 + float32 real_error; // 误差值 + + /*输出值*/ + uint16_t arr_default; // 默认计数器(推动计数值) + uint16_t arr_50_percent; // 使执行器能够稳定在百分之50阀位的控制值 + volatile uint16_t arr_current; // 当前推动阀门的计数器 + volatile uint16_t arr_last; // 上一次计数器值 +} pwmp_hd_test_t; + +typedef enum +{ + PWMP_HD_ADJUST_IDEL, + PWMP_HD_ADJUST_ROUGH_POSITION0, // 粗调位置0 + PWMP_HD_ADJUST_ACCURATE_POSITION0, // 精调位置0 + PWMP_HD_ADJUST_ROUGH_POSITION100, // 粗调位置100 + PWMP_HD_ADJUST_ACCURATE_POSITION100, // 精调位置100 + PWMP_HD_ADJUST_ALL_CLOSE_TIME, // 全关时间 + PWMP_HD_ADJUST_ALL_OPEN_TIME, // 全开时间 + PWMP_HD_ADJUST_CALCULATE, // 阀门参数计算 + PWMP_HD_ADJUST_PID_CALCULATE, // PID参数计算 + PWMP_HD_ADJUST_PID_TUNING, // PID参数自整定过程(整定得到K、T、L) + PWMP_HD_ADJUST_SAVE, // 存储变量 + PWMP_HD_ADJUST_BLEEDING, // 在整定状态中放气 + PWMP_HD_ADJUST_BLEEDING_POSITION0, // 放气位置0 + PWMP_HD_ADJUST_STOP, + PWMP_HD_ADJUST_FAIL, // 整定失败 + PWMP_HD_ADJUST_TEST, + PWMP_HD_ADJUST_BLEEDING_TIMER, + PWMP_HD_ADJUST_AERATE_TIMER, + PWMP_HD_ADJUST_TUNING, +} mode_pwmp_hd_adjust_state_e; // 整定状态 + +#define PWMP_HD_ADJUST_STEP LCD_ADJUST_STOP // 整定步骤 + +typedef enum +{ + // 自整定结果 0:未整定 1:整定中 2:整定完成 3:整定失败 + PWMP_HD_ADJUST_RESULT_IDEL = 0, + PWMP_HD_ADJUST_RESULT_TUNING, + PWMP_HD_ADJUST_RESULT_SUCCESS, + PWMP_HD_ADJUST_RESULT_FAIL, +} mode_pwmp_hd_adjust_result_e; // 整定结果 + +typedef struct +{ + mode_pwmp_hd_adjust_state_e adjust_state; + + volatile uint16_t wait_count; + volatile uint16_t psb_adc; + volatile uint16_t last_adc; + uint8_t adc_count; + BOOL preheat; + + BOOL adc_0_100_flag; // 判断0-100移动过程中ad值是增大还是减少,TRUE 增大,FALSE 减小 + BOOL flag_stable_begin; + BOOL flag_stable_end; + + uint16_t adc_record_0; // 记录放气时阀门最小位置ad值 + uint16_t adc_record_1; // 记录放气时阀门最小位置ad值 + uint16_t adc_record_2; // 记录充气时阀门最大位置ad值 + + uint16_t arr_record_0; // 最低位置阀门的ad值 + uint16_t arr_record_1; // 最小推动阀门的ad值 + uint16_t arr_record_2; // 最大位置阀门的ad值 + uint16_t arr_record_stable; // 记录使阀位稳定的ad值 + uint16_t arr_record_stable_begin; // 记录阀门稳定区域开始的ad值 + uint16_t arr_record_stable_end; // 记录阀门稳定区域结束的ad值 + + uint32_t all_open_time; // 全开时间 + uint32_t all_open_time_full; // 信号为最大输出时的全开时间 + uint32_t all_close_time; // 全关时间 + BOOL all_close_time_flag; + uint32_t tmp_time; // 临时用来记录全开全关/整定时间 + + /*输出值*/ + uint16_t arr_default; // 默认计数器(推动计数值) + volatile uint16_t arr_current; // 当前推动阀门的计数器 + volatile uint16_t arr_last; // 上一次计数器值 +} pwmp_hd_adjust_t; + +/////////////////////////////////////////*共用部分END*////////////////////////////////////////////////// + +/////////////////////////////////////////*PID参数自整定部分BEGIN*//////////////////////////////////////// +/*PID整定方法*/ +typedef enum +{ + PID_AUTOTUNE_WAY_ZN = 1, + PID_AUTOTUNE_WAY_CC, +} pid_autotune_way_e; + +/*阶跃信号大小*/ +typedef enum +{ + FULL_TRIP = 1, + HALF_TRIP, + SMALL_TRIP, +} step_signal_value; + +/*PID整定过程数据*/ +typedef struct +{ + float32 pre_actual; // 前一次的行程 + float32 cur_actual; // 当前的行程 + float32 adjust_tmp_actual; // 临时行程 + float32 actual_error; // 行程的误差 + float32 step_signal; // 阶跃信号 + float32 step_signal_delt; // 阶跃信号差值 + float32 ouput_signal_delta; // 输出信号差值 + float32 input_range; // 输入范围 + float32 output_range; // 输出范围 + float32 input_scale; // 输入比例 + float32 output_scale; // 输出比例 + float32 slope; // 变化率 + float32 slope_Max; // 最大变化率 + float32 actual_slope_Max; // 最大变化率时的行程 + uint32_t pid_autotune_time_origin; // PID自整定初始时间 + uint32_t time_slope_Max; // 最大变化率时的时间节点 + uint32_t time_Runing; // 自整定程序运行的总时间 + float32 actual_stable; // 稳定时的阀位 + float32 k; // 切线斜率 + float32 b; // 切线截距 +} pid_auto_process_data; + +/*PID参数自整定主体结构体*/ +typedef struct PID_AUTOTUNE_HD +{ + uint8_t autotune_way; // 整定的方式 + uint8_t signal_value; // 阶跃信号的大小 + float32 k_hd; // 增益 + float32 t_hd; // 时间常数 + float32 l_hd; // 延时时间 + float32 p_auto_hd; // 整定输出的P参数 + float32 i_auto_hd; // 整定输出的I参数 + float32 d_auto_hd; // 整定输出的D参数 + float32 ti_auto_hd; // 整定得到的积分时间 + float32 td_auto_hd; // 整定得到的微分时间 + pid_auto_process_data data; // 过程数据 + lpf_t actual_auto_lpf; // 滤波后的行程 +} pid_autotune_hd_t; + +/////////////////////////////////////////*PID参数自整定部分END*//////////////////////////////////////// + +/////////////////////////////////////////*控制算法BEGIN*//////////////////////////////////////// +typedef enum +{ + EXECUTE_PLAN_1, + EXECUTE_PLAN_2, + EXECUTE_PLAN_3, + EXECUTE_PLAN_4, +} execute_plan_hd_e; + +/// 操作标志 +typedef enum +{ + EXECUTE_HD_NONE = 0, ///< 不执行任何操作 + EXECUTE_HD_OUT = 1, ///< 执行输出 +} execute_hd_e; + +/// 返回内容 +typedef struct +{ + execute_hd_e code; ///< 操作标志 + uint16_t dac; ///< DAC值 +} execute_rsp_hd_t; +/////////////////////////////////////////*控制算法END*//////////////////////////////////////// + +void mode_pwmp_hd_init(mode_interface_req_t *req, uint16_t positioner_model, mode_pwmp_hd_params_u *params, void (*params_save_cb)(void)); +void mode_pwmp_hd_dinit(void); +void mode_pwmp_hd_process(void); +void pwmp_hd_process_state_set(mode_pwmp_hd_process_state_e state); +// extern void pwmp_control_update(filter_e type); +extern mode_pwmp_hd_t *mode_pwmp_hd; +#endif // __MODE_PWMP_HD_H__ + +/* 控制范围 +* 实验室大阀(气关): static int16_t mode_pwmp->pwmp_save->storage.pwmp_min = 613; + static int16_t mode_pwmp->pwmp_save->storage.pwmp_max = 900; + + 实验台中型阀(气开): static int16_t mode_pwmp->pwmp_save->storage.pwmp_min = 1100; + static int16_t mode_pwmp->pwmp_save->storage.pwmp_max = 2000; +*/ + +/*位置传感器区间 +实验室大阀(60mm,气关): uDevice.TravelVol100 = 1547; + uDevice.TravelVol0 = 2520; + +流量实验室中型阀(40mm,气开): uDevice.TravelVol100 = 1583; + uDevice.TravelVol0 = 2506; +*/ diff --git a/User/application/mode/说明/智能阀门定位器DAC输出控制模块软件说明.docx b/User/application/mode/说明/智能阀门定位器DAC输出控制模块软件说明.docx new file mode 100644 index 0000000000000000000000000000000000000000..d998eea9d55edd601201a8549cb0d3038f3c0b54 GIT binary patch literal 581516 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

NA_b%fHUdMvc^En;b=Fwy1 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

Ei0Z8%v?$ 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

2O!L2jd6x7l^R0?+veTupa3+}`>|C*c+MMEz$l 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 SZ<-$OXhVj$L$~ngd}3ZJL}dComLdoomE#K}2Vv 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

5F7W`+Ng>wdzNK+4}97`sOd5yG~wOcfj|g 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 +#include "eeprom_fm24.h" +#include "mode.h" + +static float32 last_travel = 0; // 上次目标值 + +/** + * @brief 设备序列号转字符串 + * @param {char} *s - 存储字符串 + * @param {uint8_t} *sn - 序列号 + * @param {uint8_t} len - 序列号长度 + * @param {uint8_t} interval - 间隔 + * @param {char} *fix - 间隔符号 + * @return {*} + * @note + */ +void dev_serial_number_to_string(char *s, uint8_t *sn, uint8_t len, uint8_t interval, char *fix) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < len; i++) + { + s[count] = NUM_TO_ASCII(*(sn + i)); + count++; + if (interval != 0) + { + if ((i + 1) % interval == 0 && count < count + len / interval) + { + s[count] = *fix; + count++; + } + } + } + + if (interval != 0) + { + s[len + len / interval - 1] = '\0'; // 添加字符串结束符 + } + else + { + s[len] = '\0'; // 添加字符串结束符 + } +} + +/** + * @brief HART长地址转字符串 + * @param {char} *s - 存储字符串 + * @param {uint8_t} *sn - 长地址 + * @param {uint8_t} len - 长地址长度 + * @return {*} + * @note + */ +void hart_long_address_to_string(char *s, uint8_t *sn, uint8_t len) +{ + for (uint8_t i = 0; i < len; i++) + { + s[i] = NUM_TO_ASCII(*(sn + i)); + } +} + +/** + * @brief 获取显示行程 + * @param {float32} in - 行程百分比 + * @return {float32} 显示行程 + * @note + */ +float32 get_show_travel(float32 in) +{ + float32 travel = in; + + if (udevice.display_travel_mode == TRAVEL_DISPLAY_REVERSE) // 反向显示 + { + travel = 100 - travel; + } + + return travel; +} + +/** + * @brief 获取PID控制行程 + * @param {float32} in - 行程百分比 + * @return {float32} PID控制行程 + * @note + */ +float32 get_pid_travel(float32 in) +{ + float32 travel = in; + + if (udevice.value_action_type == ATC) // 气关 + { + travel = 100 - travel; + } + return travel; +} + +/** + * @brief 实际行程处理 + * @param {float32} in - 实际行程 + * @return {*} + * @note + */ +float32 actual_travel_deal(float32 in) +{ + float32 travel = in; + + if (udevice.dev_work_mode != TEST_MODE) + { + // SWO输出 + swo_output_deal(travel); + // PWM输出阀位占空比 + pwm_output_deal(travel); + } + return travel; +} + +/** + * @brief PWM输出处理 + * @param {float32} in - 行程百分比 + * @return {*} + * @note + */ +void pwm_output_deal(float32 in) +{ + float32 travel = in; + + if (udevice.output_current_enable == true) // pwm输出使能 + { + pwm_output_position(travel); + } +} + +void swo_output_deal(float32 in) +{ + float32 travel = in; + + if (udevice.swo_logic[0] == TRIGGER_LOGIC_BELOW) + { + if (travel < udevice.swo_value[0]) + SWO1_OPEN(); + else + SWO1_CLOSE(); + } + else if (udevice.swo_logic[0] == TRIGGER_LOGIC_ABOVE) + { + if (travel > udevice.swo_value[0]) + SWO1_OPEN(); + else + SWO1_CLOSE(); + } + else + { + SWO1_CLOSE(); + } + + if (udevice.swo_logic[1] == TRIGGER_LOGIC_BELOW) + { + if (travel < udevice.swo_value[1]) + SWO2_OPEN(); + else + SWO2_CLOSE(); + } + else if (udevice.swo_logic[1] == TRIGGER_LOGIC_ABOVE) + { + if (travel > udevice.swo_value[1]) + SWO2_OPEN(); + else + SWO2_CLOSE(); + } + else + { + SWO2_CLOSE(); + } +} + +/** + * @brief 目标行程处理 + * @param {float32} in - 行程百分比 + * @return {float32} 目标行程 + * @note + */ +float32 target_travel_deal(float32 in) +{ + float32 travel = in; + + // 小信号切除 + travel = small_signal_deal(travel); + // 死区处理 + travel = dead_zone_deal(travel); + // 分程处理 + travel = part_travel_deal(travel); + + return travel; +} + +/** + * @brief 分程处理 + * @param {float32} *in - 行程百分比 + * @return {*} + * @note + */ +float32 part_travel_deal(float32 in) +{ + float32 travel = in; + float32 min = udevice.part_travel_lower; + float32 max = udevice.part_travel_upper; + + if (udevice.part_travel_enable == true) // 部分行程 + { + travel = (max - min) * travel * 0.01f + min; + } + + return travel; +} + +/** + * @brief 死区处理 + * @param {float32} in + * @return {*} + * @note + */ +float32 dead_zone_deal(float32 in) +{ + float32 travel = in; + float32 target_diff = fabsf(travel - last_travel); + + if (target_diff >= udevice.travel_dead) + { + last_travel = travel; + } + + return last_travel; +} + +/** + * @brief 小信号切除 + * @param {float32} *in - 行程百分比 + * @return {*} + * @note + */ +float32 small_signal_deal(float32 in) +{ + float32 travel = in; + float32 travel_cut_lower = 0; + float32 travel_cut_upper = 0; + + if (udevice.travel_cut_enable > 0) // 使能,使用设定值 + { + travel_cut_lower = udevice.travel_cut_lower; + travel_cut_upper = udevice.travel_cut_upper; + } + else // 禁用,使用默认值 + { + travel_cut_lower = 0; + travel_cut_upper = 100; + } + + // 最大最小需要快速的反应 + if (travel >= travel_cut_upper) // 上限 + { + travel = 100.0; + } + else if (travel <= travel_cut_lower) // 下限 + { + travel = 0; + } + + return travel; +} + +/** + * @brief 4~20mA输入电流转换成需要控制的阀门开度(不是显示的开度) %(1位小数,如 0~100%, 100% = 1000) + * @param {float32} in 当前输入的电流值 + * @return {float32} 阀门开度 - 百分比 + */ +float32 i2psb(float32 in) +{ + float32 deltI, ftmp; + float32 travel; + uint16_t index; + if (in < LOOP_CURRENT_MIN) + { + return 0; + } + else + { + // 计算相邻两个点之间的电流差值 + deltI = udevice.input_upper - udevice.input_lower; + deltI /= 16; + + // 判断输入电流在哪个范围内 + ftmp = in - LOOP_CURRENT_MIN; + index = ftmp / deltI; + + /* 计算百分比 + (I - Iindex) + % = ------------- * (%[index+1]-%[index]) + %[index] + deltI + */ + if (index > 15) + { + ftmp = valve_characteristics_table[udevice.valve_chart][16]; + } + else + { + ftmp = in - LOOP_CURRENT_MIN; + ftmp -= deltI * index; + ftmp /= deltI; + + ftmp *= (valve_characteristics_table[udevice.valve_chart][index + 1] - valve_characteristics_table[udevice.valve_chart][index]); + ftmp += valve_characteristics_table[udevice.valve_chart][index]; + } + } + ftmp /= 100; + /* + 定位器的正作用:输入信号I增大时,输出的气压增大 + 定位器的反作用:输入信号I增大时,输出的气压减小 + */ + + if (udevice.value_action_type == ATO) + { + // 气开 + if (udevice.dev_driver_dir == CONTROLLER_ACTING_NORMAL) + { + // 定位器正作用:电流增大->气压增大->弹簧压缩->开方向->%增大(正显示、反馈) + travel = ftmp; + } + else if (udevice.dev_driver_dir == CONTROLLER_ACTING_REVERSE) + { + // 定位器反作用:电流增大->气压减小->弹簧释放->关方向->%减小(正显示、反馈) + travel = 100 - ftmp; + } + else + { + travel = ftmp; + } + } + else + { + // 气关 + if (udevice.dev_driver_dir == CONTROLLER_ACTING_NORMAL) + { + // 定位器正作用:电流增大->气压增大->弹簧压缩->关方向->%减小(正显示、反馈) + travel = 100 - ftmp; + } + else + { + // 定位器反作用:电流增大->气压减小->弹簧释放->开方向->%增大(正显示、反馈) + travel = ftmp; + } + } + + if (travel < 0) + travel = 0; + else if (travel > 100) + travel = 100; + + return travel; +} + +/** + * @brief 温度值转换:摄氏度转华氏度 + * @param {float32} celsius 摄氏度 + * @return {float32} 华氏度 + * @note + */ +float32 temperature_c2f(float32 celsius) +{ + float32 temp = 32 + celsius * 1.8f; + return temp; +} + +/** + * @brief 压力值转换,kPa -> mPa psi bar kgf/cm2 + * @param {float32} kpa 压力值 kPa + * @param {uint16_t} unit 要转换的单位 + * @return {float32} 转换后的压力值 + * @note + */ +float32 pressure_kpa2unit(float32 kpa, uint16_t unit) +{ + float32 pre = 0; + switch (unit) + { + case PRESSURE_UNIT_Kpa: // kPa + pre = kpa; + break; + case PRESSURE_UNIT_Mpa: // mPa + pre = kpa * 0.001f; + break; + case PRESSURE_UNIT_Psi: // psi + pre = kpa * 0.145037743897f; + break; + case PRESSURE_UNIT_Bar: // bar + pre = kpa * 0.01f; + break; + case PRESSURE_UNIT_Kgf: // kgf/cm2 + pre = kpa * 0.0101972f; + break; + default: + pre = kpa; + break; + } + return pre; +} + +/** + * @brief 获取压力单位 + * @param {char} *s - 单位字符串 + * @param {uint16_t} unit - 单位 + * @return {*} + * @note + */ +void get_pressure_unit(char *s, uint16_t unit) +{ + DBG_ASSERT(s != NULL __DBG_LINE); + switch (unit) + { + case PRESSURE_UNIT_Kpa: // kPa + sprintf(s, "kPa"); + break; + case PRESSURE_UNIT_Mpa: // mPa + sprintf(s, "mPa"); + break; + case PRESSURE_UNIT_Psi: // psi + sprintf(s, "psi"); + break; + case PRESSURE_UNIT_Bar: // bar + sprintf(s, "bar"); + break; + case PRESSURE_UNIT_Kgf: // kgf/cm2 + sprintf(s, "kgf/cm2"); + break; + default: + sprintf(s, "kPa"); + break; + } +} + +/** + * @brief 将压力的 + * @param {uint16_t} psi_adc + * @return {*} + * @note + */ +float32 pressure_adc_to_percent(uint16_t psi_adc) +{ + return (float32)psi_adc * 100 / (float32)ADC_MAX; +} diff --git a/User/application/src/diagnosis.c b/User/application/src/diagnosis.c new file mode 100644 index 0000000..1d997ef --- /dev/null +++ b/User/application/src/diagnosis.c @@ -0,0 +1,784 @@ +/** + * @file diagnosis.c + * @author xxx + * @date 2023-09-05 09:18:35 + * @brief 定位器诊断模块 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#include "diagnosis.h" +#include "board.h" +#include "test_bsp.h" +#include "fal_execution.h" + +// 诊断函数集合 +void (*diagnosis_fail_fun[DIAGNOSIS_FAIL_MAX])(void); // 设备故障诊断 +void (*diagnosis_spec_fun[DIAGNOSIS_SPEC_MAX])(void); // 超出规格诊断 +void (*diagnosis_check_fun[DIAGNOSIS_CHECK_MAX])(float32 cmd); // 功能检查诊断 +void (*diagnosis_maint_fun[DIAGNOSIS_MAINT_MAX])(void); // 请求维护诊断 + +// 诊断结果统计 +diag_result_t diag_result; + +static void diagnosis_dev_realtime(void) +{ +} + +static void diagnosis_act_sum(void) +{ + // if (rt_data.save.act_cnt > udevice.act_sum_upper) + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_ACT_SUM, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_ACT_SUM, OK); + // } +} + +static void diagnosis_travel_sum(void) +{ + // if (rt_data.save.travel_cnt >= udevice.travel_sum_upper) + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_TRAVEL_SUM, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_TRAVEL_SUM, OK); + // } +} + +static void diagnosis_mem_usage(void) +{ + // uint8_t mem = 0; // 内存使用率 + // // 内存占比检测 + // mem = my_mem_perused(SRAMIN); + + // if (mem >= MEM_UGAGE_MAX) + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_MEM_USAGE, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_MEM_USAGE, OK); + // } +} + +static void diagnosis_cpu_usage(void) +{ + // float32 now_time = 0; + // now_time = sys_millis(); + // if (rt_data.cpu_percent >= CPU_UGAGE_MAX) + // { + // if (cpu_diagnosis.start_tag == FALSE) + // { + // cpu_diagnosis.start_time = sys_millis(); // 记录诊断开始时间 + // cpu_diagnosis.start_tag = TRUE; // 设置诊断标志 + // } + // else + // { + // if ((now_time - cpu_diagnosis.start_time) >= 30 * 1000) // xx秒钟 + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_CPU_USAGE, FAIL); + // } + // } + // } + // else + // { + // cpu_diagnosis.start_tag = FALSE; + // diagnosis_fault_set(DIAGNOSIS_CLASS_MAINT, DIAGNOSIS_CPU_USAGE, OK); + // } +} + +void diagnosis_driver_output(float32 cmd) +{ + // pwm_output_position(cmd); +} + +void diagnosis_driver_swo2(float32 cmd) +{ + // if (cmd) + // { + // SWO2_OPEN(); + // } + // else + // { + // SWO2_CLOSE(); + // } +} + +void diagnosis_driver_swo1(float32 cmd) +{ + // if (cmd) + // { + // SWO1_OPEN(); + // } + // else + // { + // SWO1_CLOSE(); + // } +} + +static void diagnosis_travel_error(void) +{ + // float32 now_time = 0; + // float32 upper = 0; + // float32 lower = 0; + // float32 target_diff = fabsf(rt_data.target_travel - travelerr_diagnosis.start_target); + // if (target_diff > udevice.travel_dead) + // { + // travelerr_diagnosis.start_target = rt_data.target_travel; // 记录诊断开始目标 + // travelerr_diagnosis.start_actual = rt_data.actual_travel; // 记录诊断开始实际 + // travelerr_diagnosis.start_time = sys_millis(); // 记录诊断开始时间 + // travelerr_diagnosis.start_tag = TRUE; // 设置诊断标志 + // } + // if (travelerr_diagnosis.start_tag) + // { + // now_time = sys_millis(); + // upper = travelerr_diagnosis.start_target * (100 + udevice.travel_error) * 0.01f; + // lower = travelerr_diagnosis.start_target * (100 - udevice.travel_error) * 0.01f; + // // 判断是否超时 + // if ((now_time - travelerr_diagnosis.start_time) >= (udevice.travel_error_time * 1000)) + // { + // // 判断阀门位置偏差 + // if ((rt_data.actual_travel <= lower) || (rt_data.actual_travel >= upper)) + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_SPEC, DIAGNOSIS_TRAVEL_ERROR, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_SPEC, DIAGNOSIS_TRAVEL_ERROR, OK); + // } + // // 清除标志 + // osel_memset((uint8_t *)&travelerr_diagnosis, 0x00, sizeof(diagnosis_t)); + // } + // } +} + +static void diagnosis_travel_lower(void) +{ +} + +static void diagnosis_travel_upper(void) +{ +} + +static void diagnosis_elasticity_lower(void) +{ +} + +static void diagnosis_elasticity_upper(void) +{ +} + +static void diagnosis_friction_lower(void) +{ +} + +static void diagnosis_friction_upper(void) +{ +} + +static void diagnosis_supply_error(void) +{ +} + +static void diagnosis_supply_lower(void) +{ +} + +static void diagnosis_supply_upper(void) +{ +} + +static void diagnosis_temperature_lower(void) +{ +} + +static void diagnosis_temperature_upper(void) +{ +} + +static void diagnosis_press_sensor_b(void) +{ +} + +static void diagnosis_press_sensor_a(void) +{ +} + +static void diagnosis_press_sensor_s(void) +{ +} + +static void diagnosis_micro_loop(void) +{ +} + +static void diagnosis_magnet(void) +{ + // uint16_t magnet_adc = adc_result_average(ADCS_1, ADC_PSB_CHANNEL); + + // if (magnet_adc < magnet_param_table[udevice.magnet_spec][0] || + // magnet_adc > magnet_param_table[udevice.magnet_spec][1]) + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_MAGNET, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_MAGNET, OK); + // } +} + +static void diagnosis_rtc(void) +{ + // rtc_date date; + + // if (FALSE == test_rtc(RTC_READ, &date)) + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_RTC, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_RTC, OK); + // } +} + +static void diagnosis_eeprom_lc02(void) +{ +} + +static void diagnosis_eeprom_fm24(void) +{ +} + +static void diagnosis_eeprom_m95_2(void) +{ +} + +static void diagnosis_eeprom_m95_1(void) +{ +} + +static void diagnosis_ip_driver(void) +{ + // uint8_t ret = TRUE; + // uint8_t mode = get_pdctrl_mode(); + // if (mode == PDCTRL_DAC) + // { + // ret = test_ip_putput_dac(rt_data.ip_output); + // } + // else if (mode == PDCTRL_PWM) + // { + // uint16_t duty = calculate_pwm_duty(rt_data.ip_output); + // float32 percent = (float32)duty / (float32)(pdctrl_get()->pwm_arr_default); + // ret = test_ip_putput_pwm(percent); + // } + // else if (mode == PDCTRL_PWMP) + // { + // float32 percent = (float32)rt_data.ip_output / (float32)(pdctrl_get()->pwm_arr_default); + // ret = test_ip_putput_pwm(percent); + // } + // else + // { + // return; + // } + + // if (ret == FALSE) + // { + // diagnosis_fault_set(DIAGNOSIS_IP_DRIVER, FAIL); + // } + // else + // { + // diagnosis_fault_set(DIAGNOSIS_IP_DRIVER, OK); + // } +} + +static void diagnosis_input_lower(void) +{ + float32 pro_current = rt_data.loop_current; + + if (pro_current > udevice.input_lower) + { + diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_INPUT_LOWER, FAIL); + } + else + { + diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_INPUT_LOWER, OK); + } +} + +static void diagnosis_input_upper(void) +{ + float32 pro_current = rt_data.loop_current; + + if (pro_current > udevice.input_upper) + { + diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_INPUT_UPPER, FAIL); + } + else + { + diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_INPUT_UPPER, OK); + } +} + +static void diagnosis_vref(void) +{ + diag_process_t pro_vref; + osel_memset((uint8_t *)&pro_vref, 0x00, sizeof(diag_process_t)); + + uint16_t vref_adc = 0; + float32 cur_vref = 0.0f, dif_vref = 0.0f; + uint32_t cur_time = 0, dif_time = 0; + + // 采集基准电压的ADC值 + vref_adc = adc_result_average(ADCS_1, ADC_INVREF_CHANNEL); + + // 基准电压诊断 + cur_vref = (float32)adc_result_value_local(vref_adc) / 1000; + dif_vref = fabs(cur_vref - CPU_VREF); + if (dif_vref > udevice.vref_error) + { + // 产生偏差,记录开始时间 + if (pro_vref.start_tag != TRUE) + { + pro_vref.start_tag = TRUE; + pro_vref.start_time = sys_millis(); + } + // 产生偏差超时,设置故障 + else + { + cur_time = sys_millis(); + dif_time = (cur_time - pro_vref.start_time) / 1000; + if (dif_time >= udevice.vref_error_time) + { + diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_VREF, FAIL); + } + } + } + else + { + diagnosis_fault_set(DIAGNOSIS_CLASS_FAIL, DIAGNOSIS_VREF, OK); + } +} + +/*******************************************************************************************************************/ + +/** + * @brief 诊断模块初始化 + * @return {*} + * @note 在params_init()之后调用 + */ +void diagnosis_init(void) +{ + osel_memset((uint8_t *)&diag_result, 0x00, sizeof(diag_result_t)); + diag_result.record[DIAGNOSIS_CLASS_FAIL].fault_msg = osel_mem_alloc(sizeof(diag_msg_t) * DIAGNOSIS_FAIL_MAX); + diag_result.record[DIAGNOSIS_CLASS_SPEC].fault_msg = osel_mem_alloc(sizeof(diag_msg_t) * DIAGNOSIS_SPEC_MAX); + diag_result.record[DIAGNOSIS_CLASS_CHECK].fault_msg = osel_mem_alloc(sizeof(diag_msg_t) * DIAGNOSIS_CHECK_MAX); + diag_result.record[DIAGNOSIS_CLASS_MAINT].fault_msg = osel_mem_alloc(sizeof(diag_msg_t) * DIAGNOSIS_MAINT_MAX); + + // 设备故障 + diagnosis_fail_fun[DIAGNOSIS_VREF] = diagnosis_vref; + diagnosis_fail_fun[DIAGNOSIS_INPUT_UPPER] = diagnosis_input_upper; + diagnosis_fail_fun[DIAGNOSIS_INPUT_LOWER] = diagnosis_input_lower; + diagnosis_fail_fun[DIAGNOSIS_IP_DRIVER] = diagnosis_ip_driver; + diagnosis_fail_fun[DIAGNOSIS_EEPROM_M95_1] = diagnosis_eeprom_m95_1; + diagnosis_fail_fun[DIAGNOSIS_EEPROM_M95_2] = diagnosis_eeprom_m95_2; + diagnosis_fail_fun[DIAGNOSIS_EEPROM_FM24] = diagnosis_eeprom_fm24; + diagnosis_fail_fun[DIAGNOSIS_EEPROM_LC02] = diagnosis_eeprom_lc02; + diagnosis_fail_fun[DIAGNOSIS_RTC] = diagnosis_rtc; + diagnosis_fail_fun[DIAGNOSIS_MAGNET] = diagnosis_magnet; + diagnosis_fail_fun[DIAGNOSIS_MICRO_LOOP] = diagnosis_micro_loop; + diagnosis_fail_fun[DIAGNOSIS_PRESS_SENSOR_S] = diagnosis_press_sensor_s; + diagnosis_fail_fun[DIAGNOSIS_PRESS_SENSOR_A] = diagnosis_press_sensor_a; + diagnosis_fail_fun[DIAGNOSIS_PRESS_SENSOR_B] = diagnosis_press_sensor_b; + // 超出规格 + diagnosis_spec_fun[DIAGNOSIS_TEMPERATURE_UPPER] = diagnosis_temperature_upper; + diagnosis_spec_fun[DIAGNOSIS_TEMPERATURE_LOWER] = diagnosis_temperature_lower; + diagnosis_spec_fun[DIAGNOSIS_SUPPLY_UPPER] = diagnosis_supply_upper; + diagnosis_spec_fun[DIAGNOSIS_SUPPLY_LOWER] = diagnosis_supply_lower; + diagnosis_spec_fun[DIAGNOSIS_SUPPLY_ERROR] = diagnosis_supply_error; + diagnosis_spec_fun[DIAGNOSIS_FRICTION_UPPER] = diagnosis_friction_upper; + diagnosis_spec_fun[DIAGNOSIS_FRICTION_LOWER] = diagnosis_friction_lower; + diagnosis_spec_fun[DIAGNOSIS_ELASTICITY_UPPER] = diagnosis_elasticity_upper; + diagnosis_spec_fun[DIAGNOSIS_ELASTICITY_LOWER] = diagnosis_elasticity_lower; + diagnosis_spec_fun[DIAGNOSIS_TRAVEL_UPPER] = diagnosis_travel_upper; + diagnosis_spec_fun[DIAGNOSIS_TRAVEL_LOWER] = diagnosis_travel_lower; + diagnosis_spec_fun[DIAGNOSIS_TRAVEL_ERROR] = diagnosis_travel_error; + // 功能检查 + diagnosis_check_fun[DIAGNOSIS_DRIVER_SWO1] = diagnosis_driver_swo1; + diagnosis_check_fun[DIAGNOSIS_DRIVER_SWO2] = diagnosis_driver_swo2; + diagnosis_check_fun[DIAGNOSIS_DRIVER_OUTPUT] = diagnosis_driver_output; + // 请求维护 + diagnosis_maint_fun[DIAGNOSIS_CPU_USAGE] = diagnosis_cpu_usage; + diagnosis_maint_fun[DIAGNOSIS_MEM_USAGE] = diagnosis_mem_usage; + diagnosis_maint_fun[DIAGNOSIS_TRAVEL_SUM] = diagnosis_travel_sum; + diagnosis_maint_fun[DIAGNOSIS_ACT_SUM] = diagnosis_act_sum; + diagnosis_maint_fun[DIAGNOSIS_DEV_REALTIME] = diagnosis_dev_realtime; +} + +/** + * @brief 设置诊断状态 + * @param {diag_fail_e} code + * @param {uint8_t} state + * @return {*} + * @note + */ +void diagnosis_fault_set(diag_class_e class, uint8_t code, uint8_t state) +{ + uint8_t *fault_cnt = (uint8_t *)&diag_result.record[class].fault_cnt; + diag_msg_t *fault_msg = (diag_msg_t *)diag_result.record[class].fault_msg; + fault_msg += code; + + // 状态没有改变,不需要更新诊断结果 + if (fault_msg->diag_state == state) + { + return; + } + + // 状态发生改变,需要更新诊断结果 + if (state == OK) + { + // 清除标志 + fault_msg->diag_state = state; + // 更新清除时间 + osel_memcpy((uint8_t *)fault_msg->last_clear_time.Byte, (uint8_t *)rt_data.save.real_time.Byte, 6); + // 更新故障数量 + *fault_cnt--; + } + else + { + // 设置标志 + fault_msg->diag_state = state; + // 更新产生时间 + osel_memcpy((uint8_t *)fault_msg->last_mark_time.Byte, (uint8_t *)rt_data.save.real_time.Byte, 6); + osel_memset((uint8_t *)fault_msg->last_mark_time.Byte, 0x00, 6); + // 更新故障数量 + *fault_cnt++; + } +} + +/** + * @brief 诊断结果最高等级检查 + * @return {*} + * @note + */ +void diagnosis_priority_check(void) +{ + if (diag_result.record[DIAGNOSIS_CLASS_FAIL].fault_cnt != 0) + { + diag_result.priority = DIAGNOSIS_CLASS_FAIL; + } + else if (diag_result.record[DIAGNOSIS_CLASS_SPEC].fault_cnt != 0) + { + diag_result.priority = DIAGNOSIS_CLASS_SPEC; + } + else if (diag_result.record[DIAGNOSIS_CLASS_CHECK].fault_cnt != 0) + { + diag_result.priority = DIAGNOSIS_CLASS_CHECK; + } + else if (diag_result.record[DIAGNOSIS_CLASS_MAINT].fault_cnt != 0) + { + diag_result.priority = DIAGNOSIS_CLASS_MAINT; + } + else + { + diag_result.priority = DIAGNOSIS_CLASS_OK; + } +} + +/** + * @brief 诊断结果led指示 + * @param {diag_class_e} sta + * @return {*} + * @note + */ +static void diagnosis_fault_indicate(diag_class_e sta) +{ + switch (sta) + { + case DIAGNOSIS_CLASS_FAIL: ///< 设备故障 + leds_on(LEDS_1_RED); + break; + case DIAGNOSIS_CLASS_SPEC: ///< 超出规格 + leds_on(LEDS_1_YELLOW); + break; + case DIAGNOSIS_CLASS_CHECK: ///< 功能检查 + leds_on(LEDS_2_ORANGE); + break; + case DIAGNOSIS_CLASS_MAINT: ///< 要求维护 + leds_on(LEDS_2_BLUE); + break; + case DIAGNOSIS_CLASS_OK: ///< 诊断正常 + leds_on(LEDS_1_GREEN); + break; + } + // 下面2行代码让面板LED强制绿色 + // leds_off_all(); + // leds_on(LEDS_1_GREEN); +} + +/** + * @brief 诊断结果处理 + * @return {*} + * @note + */ +void diagnosis_fault_deal(void) +{ + // 故障优先级检查 + diagnosis_priority_check(); + // 故障指示 + diagnosis_fault_indicate(diag_result.priority); + // 阀门控制 + if (diag_result.priority == DIAGNOSIS_CLASS_OK) + { + diag_result.cmd = ALARM_HANDLING_CONTINUE; + } + else + { + diag_result.cmd = (alarm_handle_mode_e)udevice.alarm_handle_mode; + } +} + +/** + * @brief 获取诊断故障数量 + * @param {diag_class_e} cls 故障类型 + * @return {uint8_t} 故障数量 + * @note + */ +uint8_t get_diagnosis_fault_num(diag_class_e cls) +{ + return diag_result.record[cls].fault_cnt; +} + +/** + * @brief 获取诊断故障结果 + * @param {diag_class_e} cls 故障类型 + * @param {uint8_t} code 故障代码 + * @return {state_e} + * @note + */ +state_e get_diagnosis_fault_result(diag_class_e cls, uint8_t code) +{ + diag_msg_t *fault_msg = (diag_msg_t *)diag_result.record[cls].fault_msg; + fault_msg += code; + return (state_e)fault_msg->diag_state; +} + +// /** +// * @brief 检测外部EEPROM +// * @return {*} +// * @note +// */ +// static void diagnosis_eeprom(void) +// { +// BOOL eeprom_err = FALSE; + +// eeprom_err = fal_execution_status_get(FAL_EXECUTION_EEPROM_M95_1); +// if (eeprom_err == FALSE) +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_M95_1, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_M95_1, OK); +// } + +// eeprom_err = fal_execution_status_get(FAL_EXECUTION_EEPROM_M95_2); +// if (eeprom_err == FALSE) +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_M95_2, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_M95_2, OK); +// } + +// eeprom_err = fal_execution_status_get(FAL_EXECUTION_EEPROM_FM24); +// if (eeprom_err == FALSE) +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_FM24, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_FM24, OK); +// } + +// eeprom_err = selftest_lc02(); +// if (eeprom_err == FALSE) +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_LC02, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_EEPROM_LC02, OK); +// } +// } + +// /** +// * @brief 气压传感芯片检测 +// * @return {*} +// * @note +// */ +// static void diagnosis_pressur_sensor(void) +// { +// adc_raw[ADC_BP_CHANNEL] = adc_result_average(ADCS_1, ADC_BP_CHANNEL); // 气源 +// adc_raw[ADC_BPA_CHANNEL] = adc_result_average(ADCS_1, ADC_BPA_CHANNEL); // A +// adc_raw[ADC_BPB_CHANNEL] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL); // B + +// if ((adc_raw[ADC_BP_CHANNEL] > pressure_param_table[PRESSURE_PARAM_S][1]) || +// (adc_raw[ADC_BP_CHANNEL] < pressure_param_table[PRESSURE_PARAM_S][0])) +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_S, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_S, OK); +// } + +// if ((adc_raw[ADC_BPA_CHANNEL] > pressure_param_table[PRESSURE_PARAM_A][1]) || +// (adc_raw[ADC_BPA_CHANNEL] < pressure_param_table[PRESSURE_PARAM_A][0])) +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_A, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_A, OK); +// } + +// if (udevice.value_relay_type == VALVE_ACTING_DOUBLE) // 双作用,检测B通道 +// { +// if ((adc_raw[ADC_BPB_CHANNEL] > pressure_param_table[PRESSURE_PARAM_B][1]) || +// (adc_raw[ADC_BPB_CHANNEL] < pressure_param_table[PRESSURE_PARAM_B][0])) +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_B, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_B, OK); +// } +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_PRESS_SENSOR_B, OK); +// } +// } + +// /** +// * @brief 温度检测 +// * @return {*} +// * @note +// */ +// static void diagnosis_temperature(void) +// { +// if (rt_data.temperature >= udevice.temp_upper) +// { +// diagnosis_fault_set(DIAGNOSIS_TEMPERATURE_UPPER, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_TEMPERATURE_UPPER, OK); +// } + +// if (rt_data.temperature <= udevice.temp_lower) +// { +// diagnosis_fault_set(DIAGNOSIS_TEMPERATURE_LOWER, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_TEMPERATURE_LOWER, OK); +// } +// } + +// /** +// * @brief 气源压力检测 +// * @return {*} +// * @note +// */ +// static void diagnosis_supply_press(void) +// { +// float32 now_time = 0; +// float32 upper = 0; +// float32 lower = 0; +// float32 trans_pressure = 0; + +// if (pressure_diagnosis.start_tag) +// { +// now_time = sys_millis(); +// upper = pressure_diagnosis.start_target * (100 + udevice.supply_error) * 0.01f; +// lower = pressure_diagnosis.start_target * (100 - udevice.supply_error) * 0.01f; +// // 判断是否超时 +// if ((now_time - pressure_diagnosis.start_time) >= (udevice.supply_error_time * 1000)) +// { +// // 单位转换 +// trans_pressure = pressure_kpa2unit(rt_data.pressure_s, udevice.press_unit); +// // 判断气压偏差 +// if (trans_pressure >= upper) +// { +// diagnosis_fault_set(DIAGNOSIS_SUPPLY_UPPER, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_SUPPLY_UPPER, OK); +// } +// if (trans_pressure <= lower) +// { +// diagnosis_fault_set(DIAGNOSIS_SUPPLY_LOWER, FAIL); +// } +// else +// { +// diagnosis_fault_set(DIAGNOSIS_SUPPLY_LOWER, OK); +// } +// // 清除标志 +// osel_memset((uint8_t *)&pressure_diagnosis, 0x00, sizeof(diagnosis_t)); +// } +// } +// else +// { +// pressure_diagnosis.start_target = udevice.supply_press; // 记录诊断开始目标 +// pressure_diagnosis.start_actual = rt_data.pressure_s; // 记录诊断开始实际 +// pressure_diagnosis.start_time = sys_millis(); // 记录诊断开始时间 +// pressure_diagnosis.start_tag = TRUE; // 设置诊断标志 +// } +// } + +/** + * @brief 开机自检 + * @return {*} + * @note + */ +void power_on_diagnosis(void) +{ + diagnosis_vref(); // 基准电压故障 + // diagnosis_input(); // 输入电流故障 + // diagnosis_eeprom(); // 存储器故障 + // diagnosis_rtc(); // RTC故障 + // diagnosis_travel_sum(); // 累计行程报警 + // diagnosis_act_number(); // 动作次数报警 +} + +/** + * @brief 过程诊断 + * @return {*} + * @note + */ +void diagnosis_inspection(void) +{ + // diagnosis_vref(CPU_VREF); // 基准电压故障 + // diagnosis_input(); // 输入电流故障 + // diagnosis_ip(); // I/P驱动故障 + // diagnosis_magnet(); // 磁条反馈诊断 + // diagnosis_micro_loop(); // 小回路反馈诊断 + // diagnosis_pressur_sensor(); // 气压传感器诊断 + // diagnosis_temperature(); // 温度上下限报警 -50~80 + // diagnosis_supply_press(); // 气源压力报警 + // diagnosis_friction(); // 摩擦力报警 + // diagnosis_elasticity(); // 弹簧力报警 + // diagnosis_travel_limit(); // 行程高限位报警 + // diagnosis_travel_err(); // 行程偏差报警 + // diagnosis_dead_zone(); // 死区上限报警 + // diagnosis_cpu(100); // CPU故障 + // diagnosis_mem(90); // 内存故障 + // diagnosis_travel_sum(); // 累计行程报警 + // diagnosis_act_number(); // 动作次数报警 + // diagnosis_clock(); // 设备时间诊断 +} diff --git a/User/application/src/fal_execution.c b/User/application/src/fal_execution.c new file mode 100644 index 0000000..033147d --- /dev/null +++ b/User/application/src/fal_execution.c @@ -0,0 +1,583 @@ +/** + * @file fal_execution.c + * @author xxx + * @date 2023-12-29 11:27:55 + * @brief + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ + +/** + * +存储模块是一个用于存储和读取数据的函数,它使用了 FAL(Flash Abstraction Layer)库来实现。FAL 库是一个用于访问 Flash 存储器的抽象层, +它提供了一组标准的接口,使得应用程序可以方便地访问 Flash 存储器中的数据。在这段代码中,函数 fal_execution_kv_read() +用于从 KV(Key-Value)存储中读取指定键的值,函数 fal_execution_kv_write() 用于向指定的 KV 存储中写入一个键值对。 +函数 fal_execution_inspection() 用于对数据进行检查和存储。在函数 fal_execution_kv_read() 中,首先使用函数 fal_execution_get() +将给定的键转换为相应的执行结构,然后调用函数 fdb_kv_get_blob() 从 KV 存储中读取数据并存储在 blob 变量中。如果读取到的数据长度大于 0, +则调用函数 fal_execution_set_crc() 和 fal_execution_set_cmac() 对数据进行 CRC 和 CMAC 校验,并返回 TRUE。否则返回 FALSE。 +在函数 fal_execution_kv_write() 中,首先使用函数 fal_execution_get() 将给定的键转换为相应的执行结构,然后调用函数 +fdb_kv_set_blob() 将数据写入 KV 存储。如果写入操作成功,则调用函数 fal_execution_set_crc() 和 fal_execution_set_cmac() +对数据进行 CRC 和 CMAC 校验,并返回 TRUE。否则返回 FALSE。在函数 fal_execution_inspection() 中, +首先检查 M95_1 和 FM24 两个执行结构是否已经初始化,如果已经初始化,则对校准参数、设备参数、HART 参数和 HART 用户参数进行检查和存储。 +如果存储失败,则将相应的执行结构的状态标志位设置为 0。如果 FM24 已经初始化,则每隔一段时间对实时数据进行存储。 +*/ +#include "fal_execution.h" +#include "board.h" +#include "sys.h" +#include "entity.h" +#include "cmac.h" + +#define FAL_DBG_ENABLE 0 // 等测试完成后再删除 + +const char *FAL_KV_KEY[KEY_MAX] = + { + "calibpara_param", + "device", + "hart_device_variable_param", + "real_time_data", + "mode_param", +}; +static fal_execution_status_t fal_execution_status; // eeprom状态 +static fal_execution_t fal_executions[FAL_EXECUTION_MAX]; +static struct fdb_default_kv_node m95_1_kv_table[] = { + {(char *)&FAL_KV_KEY[KEY_CALIBPARA_PARAM], &calib_param, sizeof(calib_param_t) * CALIBPARA_NUM}, // 校准参数 + {(char *)&FAL_KV_KEY[KEY_DEVICE], &udevice, sizeof(device_typedef)}, // 设备内设置的信息 + {(char *)&FAL_KV_KEY[KEY_MODE_PARAM], &mode_params, sizeof(mode_params_t)}, // 模式参数:控制算法自定义参数 +}; +static struct fdb_default_kv_node fm24_kv_table[] = { + {(char *)&FAL_KV_KEY[KEY_REAL_TIME_DATA], &rt_data, sizeof(real_time_data_t)}, // 实时数据 +}; + +// 数据加密校验 +typedef struct +{ + uint8_t mic[4]; +} fal_inspection_cmac_t; + +static uint8_t cmac_key[] = { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥 +static uint16_t fal_inspection_crc[KEY_MAX]; // 用于保存结构体CRC值,保证相同数据内容不写入 +static fal_inspection_cmac_t fal_inspection_cmac[KEY_MAX]; // 用于保存结构体CMAC值,保证相同数据内容不写入 + +// 内部接口 // 获取时间戳 +static fal_execution_t *fal_execution_get(const fal_key_e key); // 获取fal_execution_t结构体 +static void fal_execution_set_crc(const uint8_t index, const uint8_t *const data, const uint16_t length); // 数据的CRC计算 +static void fal_execution_set_cmac(const uint8_t index, const uint8_t *const data, const uint16_t length); // 数据的CMAC计算 +static BOOL fal_execution_data_storage_check(const uint8_t index, const uint8_t *const data, const uint16_t length); // 数据的校验 +/** + * @brief fal执行初始化 + * @return {*} + * @note + */ +void fal_execution_init(void) +{ + fal_execution_status.init.data = 0; + fal_execution_status.read.data = 0; + fal_execution_status.write.data = 0; + + fal_execution_t *p = NULL; + fdb_err_t res = FDB_NO_ERR; + osel_memset((uint8_t *)&fal_inspection_crc, 0, sizeof(uint16_t) * KEY_MAX); + + // 初始化M95_1 + p = &fal_executions[FAL_EXECUTION_EEPROM_M95_1]; + p->eeprom_index = FAL_EXECUTION_EEPROM_M95_1; + p->kv.kvs = m95_1_kv_table; + p->kv.num = ARRAY_LEN(m95_1_kv_table); + fdb_kvdb_control(&p->kvdb, FDB_KVDB_CTRL_SET_LOCK, NULL); + fdb_kvdb_control(&p->kvdb, FDB_KVDB_CTRL_SET_UNLOCK, NULL); + res = fdb_kvdb_init(&p->kvdb, "env", "KVDB", &p->kv, NULL); + if (res != FDB_NO_ERR) + { + fal_execution_status.init.bits.M95_1 = 0; + fal_execution_status.read.bits.M95_1 = 0; + fal_execution_status.write.bits.M95_1 = 0; + } + else + { + fal_execution_status.init.bits.M95_1 = 1; + fal_execution_status.read.bits.M95_1 = 1; + fal_execution_status.write.bits.M95_1 = 1; + } + + // 初始化M95_2 + p = &fal_executions[FAL_EXECUTION_EEPROM_M95_2]; + p->eeprom_index = FAL_EXECUTION_EEPROM_M95_2; + fdb_tsdb_control(&p->tsdb, FDB_TSDB_CTRL_SET_LOCK, NULL); + fdb_tsdb_control(&p->tsdb, FDB_TSDB_CTRL_SET_UNLOCK, NULL); + res = fdb_tsdb_init(&p->tsdb, "log", "TSDB", fal_execution_get_time, 128, NULL); + if (res != FDB_NO_ERR) + { + fal_execution_status.init.bits.M95_2 = 0; + fal_execution_status.read.bits.M95_2 = 0; + fal_execution_status.write.bits.M95_2 = 0; + } + else + { + fal_execution_status.init.bits.M95_2 = 1; + fal_execution_status.read.bits.M95_2 = 1; + fal_execution_status.write.bits.M95_2 = 1; + } + + // 初始化FM24 + p = &fal_executions[FAL_EXECUTION_EEPROM_FM24]; + p->eeprom_index = FAL_EXECUTION_EEPROM_FM24; + p->kv.kvs = fm24_kv_table; + p->kv.num = ARRAY_LEN(fm24_kv_table); + fdb_kvdb_control(&p->kvdb, FDB_KVDB_CTRL_SET_LOCK, NULL); + fdb_kvdb_control(&p->kvdb, FDB_KVDB_CTRL_SET_UNLOCK, NULL); + res = fdb_kvdb_init(&p->kvdb, "env", "RTDB", &p->kv, NULL); + if (res != FDB_NO_ERR) + { + fal_execution_status.init.bits.FM24 = 0; + fal_execution_status.read.bits.FM24 = 0; + fal_execution_status.write.bits.FM24 = 0; + } + else + { + fal_execution_status.init.bits.FM24 = 1; + fal_execution_status.read.bits.FM24 = 1; + fal_execution_status.write.bits.FM24 = 1; + } +} + +/** + * @brief fal执行清除 + * @param {fal_execution_e} index + * @return {*} + * @note + */ +void fal_execution_clear(fal_execution_e index) +{ + fal_execution_t *p = NULL; + switch (index) + { + case FAL_EXECUTION_EEPROM_M95_1: + p = &fal_executions[FAL_EXECUTION_EEPROM_M95_1]; + fdb_kv_set_default(&p->kvdb); + break; + case FAL_EXECUTION_EEPROM_M95_2: + p = &fal_executions[FAL_EXECUTION_EEPROM_M95_2]; + fdb_tsl_clean(&p->tsdb); + break; + case FAL_EXECUTION_EEPROM_FM24: + p = &fal_executions[FAL_EXECUTION_EEPROM_FM24]; + fdb_kv_set_default(&p->kvdb); + break; + default: + DBG_ASSERT(FALSE __DBG_LINE); + break; + } +} + +/** + * @brief 获取fal_execution_t结构体 + * @param {fal_execution_e} index + * @return {*} + * @note + */ +static fal_execution_t *fal_execution_get(const fal_key_e key) +{ + fal_execution_t *p = NULL; + switch (key) + { + case KEY_CALIBPARA_PARAM: // 校准参数 + case KEY_DEVICE: // 设备内设置的信息 + case KEY_MODE_PARAM: // 模式参数:控制算法自定义参数 + case KEY_HART_DEVICE_VARIABLE_PARAM: // HART设备信息 + if (fal_execution_status.init.bits.M95_1 == 1) + { + p = &fal_executions[FAL_EXECUTION_EEPROM_M95_1]; + } + break; + case KEY_REAL_TIME_DATA: // 实时数据 + if (fal_execution_status.init.bits.FM24 == 1) + { + p = &fal_executions[FAL_EXECUTION_EEPROM_FM24]; + } + break; + default: + break; + } + + return p; +} + +/** + * @brief 数据的CRC计算 + * @param {uint8_t} index 数据索引 + * @param {uint8_t} *data 数据指针 + * @param {uint16_t} length 数据长度 + * @return {*} + * @note + */ +static void fal_execution_set_crc(const uint8_t index, const uint8_t *const data, const uint16_t length) +{ + uint16_t crc = crc16_compute(data, length); + fal_inspection_crc[index] = crc; +} + +/** + * @brief 数据的CMAC计算 + * @param {uint8_t} index 数据索引 + * @param {uint8_t} *data 数据指针 + * @param {uint16_t} length 数据长度 + * @return {*} + * @note + */ +static void fal_execution_set_cmac(const uint8_t index, const uint8_t *const data, const uint16_t length) +{ + uint8_t mic[16]; + uint8_t *p; + AES_CMAC_CTX AesCmacCtx[1]; // 密钥扩展表 + AES_CMAC_Init(AesCmacCtx); // 完成密钥扩展表的初始化 + AES_CMAC_SetKey(AesCmacCtx, cmac_key); // 完成密钥扩展表数据 // 存放生成校验数据的数组 + AES_CMAC_Update(AesCmacCtx, data, length & 0xFF); // 完成数据的奇偶校验 + AES_CMAC_Final(mic, AesCmacCtx); // 生成16个字节的校验表 + uint32_t xor_vol = (uint32_t)((uint32_t)mic[3] << 24 | (uint32_t)mic[2] << 16 | (uint32_t)mic[1] << 8 | (uint32_t)mic[0]); // 取表4个字节作为校验码 + p = (uint8_t *)&xor_vol; + osel_memcpy(fal_inspection_cmac[index].mic, p, 4); +} +/** + * @brief 数据的校验 + * @param {uint8_t} index 数据索引 + * @param {uint8_t} *data 数据指针 + * @param {uint16_t} length 数据长度 + * @return {*} + * @note 这个函数用于对数据进行校验,包括CRC校验和CMAC校验。 + */ +static BOOL fal_execution_data_storage_check(const uint8_t index, const uint8_t *const data, const uint16_t length) +{ + // CRC校验 + { + uint16_t crc = 0; + crc = crc16_compute(data, length); + if (crc != fal_inspection_crc[index]) + { + return FALSE; + } + } + + // CMAC校验 + { + uint8_t mic[16]; + uint8_t *p; + AES_CMAC_CTX AesCmacCtx[1]; // 密钥扩展表 + AES_CMAC_Init(AesCmacCtx); // 完成密钥扩展表的初始化 + AES_CMAC_SetKey(AesCmacCtx, cmac_key); // 完成密钥扩展表数据 // 存放生成校验数据的数组 + AES_CMAC_Update(AesCmacCtx, data, length & 0xFF); // 完成数据的奇偶校验 + AES_CMAC_Final(mic, AesCmacCtx); // 生成16个字节的校验表 + uint32_t xor_vol = (uint32_t)((uint32_t)mic[3] << 24 | (uint32_t)mic[2] << 16 | (uint32_t)mic[1] << 8 | (uint32_t)mic[0]); // 取表4个字节作为校验码 + p = (uint8_t *)&xor_vol; + + if (osel_memcmp(fal_inspection_cmac[index].mic, p, 4) != 0) + { + return FALSE; + } + } + + return TRUE; +} + +fdb_time_t fal_execution_get_time(void) +{ + /* Using the counts instead of timestamp. + * Please change this function to return RTC time. + */ + rtc_date_t dd; + rtc_time_t tt; + uDateTime_TypeDef timestamp; // 时间戳 + get_timestamp((uDateTime_TypeDef *)×tamp); + dd.year = hex_format_dec(timestamp.Date.Year); + dd.month = hex_format_dec(timestamp.Date.Month); + dd.day = hex_format_dec(timestamp.Date.Day); + tt.hour = hex_format_dec(timestamp.Date.Hour); + tt.minute = hex_format_dec(timestamp.Date.Minute); + tt.second = hex_format_dec(timestamp.Date.Second); + + return (int32_t)time2stamp(dd, tt); +} +/** + * 从 KV 存储中读取指定键的值 + * + * @param key 要从 KV 存储中读取的键 + * @param data 用于存储读取到的数据的缓冲区 + * @param length 缓冲区的长度 + * + * @return true 如果读取操作成功,false 否则 + * + * @note 此函数从 KV 存储中读取指定键的值。首先,它检查给定的键是否与任何预定义的键匹配,如果是,则将相应的执行结构分配给 'p' 变量。然后,它调用 fdb_kv_get_blob() 函数从 KV 存储中读取数据并返回结果。如果给定的键不与任何预定义的键匹配,则断言条件为 false 并返回 false。 + */ +BOOL fal_execution_kv_read(const fal_key_e key, const uint8_t *data, uint16_t length) +{ + DBG_ASSERT(FAL_KV_KEY[key] != NULL __DBG_LINE); + BOOL rv = FALSE; + struct fdb_blob blob; // 定义一个 fdb_blob 结构体变量 blob + fal_execution_t *p = fal_execution_get(key); // 将给定的键转换为相应的执行结构 + if (p == NULL) + { + return FALSE; + } + + fdb_kv_get_blob(&p->kvdb, FAL_KV_KEY[key], fdb_blob_make(&blob, data, length)); // 从 KV 存储中读取数据并存储在 blob 变量中 + if (blob.saved.len > 0) // 如果 blob 变量中的数据长度大于 0 + { + fal_execution_set_crc((uint8_t)key, data, length); // 数据的CRC计算 + fal_execution_set_cmac((uint8_t)key, data, length); // 数据的CMAC计算 + rv = TRUE; // 返回 true + } + else + { + rv = FALSE; // 返回 false + } + switch (p->eeprom_index) + { + case FAL_EXECUTION_EEPROM_M95_1: + fal_execution_status.read.bits.M95_1 = rv == TRUE ? 1 : 0; + break; + case FAL_EXECUTION_EEPROM_M95_2: + fal_execution_status.read.bits.M95_2 = rv == TRUE ? 1 : 0; + break; + case FAL_EXECUTION_EEPROM_FM24: + fal_execution_status.read.bits.FM24 = rv == TRUE ? 1 : 0; + break; + default: + DBG_ASSERT(FALSE __DBG_LINE); + break; + } + return rv; +} + +/** + * @brief 向指定的 KV 存储中写入一个键值对。 + * + * @param key 要写入 KV 存储的键。 + * @param data 要写入 KV 存储的数据。 + * @param length 要写入 KV 存储的数据长度。 + * + * @return true 如果写入操作成功,false 否则。 + * + * @note 此函数将向指定的键在 KV 存储中写入一个键值对。首先,它将检查给定的键是否与任何预定义的键匹配,如果是,则将相应的执行结构分配给 'p' 变量。然后,它调用 fdb_kv_set_blob() 函数将数据写入 KV 存储并返回结果。如果给定的键不与任何预定义的键匹配,则断言条件为 false 并返回 false。 + */ +BOOL fal_execution_kv_write(const fal_key_e key, const uint8_t *const data, const uint16_t length) +{ + DBG_ASSERT(FAL_KV_KEY[key] != NULL __DBG_LINE); + BOOL rv = FALSE; + struct fdb_blob blob; + fdb_err_t res = FDB_NO_ERR; + fal_execution_t *p = fal_execution_get(key); + if (p == NULL) + { + return FALSE; + } + + res = fdb_kv_set_blob(&p->kvdb, FAL_KV_KEY[key], fdb_blob_make(&blob, data, length)); + + if (res == FDB_NO_ERR) + { + fal_execution_set_crc((uint8_t)key, data, length); // 数据的CRC计算 + fal_execution_set_cmac((uint8_t)key, data, length); // 数据的CMAC计算 + rv = TRUE; + } + else + { + rv = FALSE; + } + + switch (p->eeprom_index) + { + case FAL_EXECUTION_EEPROM_M95_1: + fal_execution_status.read.bits.M95_1 = rv == TRUE ? 1 : 0; + break; + case FAL_EXECUTION_EEPROM_M95_2: + fal_execution_status.read.bits.M95_2 = rv == TRUE ? 1 : 0; + break; + case FAL_EXECUTION_EEPROM_FM24: + fal_execution_status.read.bits.FM24 = rv == TRUE ? 1 : 0; + break; + default: + DBG_ASSERT(FALSE __DBG_LINE); + break; + } + return rv; +} + +/** + * @brief 获取fal执行状态 + * @param {fal_execution_e} index + * @return {*} + * @note + */ +BOOL fal_execution_status_get(fal_execution_e index) +{ + BOOL init = FALSE; + BOOL read = FALSE; + BOOL write = FALSE; + switch (index) + { + case FAL_EXECUTION_EEPROM_M95_1: + init = fal_execution_status.init.bits.M95_1 == 1 ? TRUE : FALSE; + read = fal_execution_status.read.bits.M95_1 == 1 ? TRUE : FALSE; + write = fal_execution_status.write.bits.M95_1 == 1 ? TRUE : FALSE; + break; + case FAL_EXECUTION_EEPROM_M95_2: + init = fal_execution_status.init.bits.M95_2 == 1 ? TRUE : FALSE; + read = fal_execution_status.read.bits.M95_2 == 1 ? TRUE : FALSE; + write = fal_execution_status.write.bits.M95_2 == 1 ? TRUE : FALSE; + break; + case FAL_EXECUTION_EEPROM_FM24: + init = fal_execution_status.init.bits.FM24 == 1 ? TRUE : FALSE; + read = fal_execution_status.read.bits.FM24 == 1 ? TRUE : FALSE; + write = fal_execution_status.write.bits.FM24 == 1 ? TRUE : FALSE; + break; + default: + DBG_ASSERT(FALSE __DBG_LINE); + break; + } + return init && read && write; +} + +/** + * @brief 设置fal执行状态 + * @param {fal_execution_e} index + * @return {*} + * @note + */ +void fal_execution_status_set(fal_execution_e index, BOOL status) +{ + switch (index) + { + case FAL_EXECUTION_EEPROM_M95_1: + fal_execution_status.init.bits.M95_1 = status; + fal_execution_status.read.bits.M95_1 = status; + fal_execution_status.write.bits.M95_1 = status; + break; + case FAL_EXECUTION_EEPROM_M95_2: + fal_execution_status.init.bits.M95_2 = status; + fal_execution_status.read.bits.M95_2 = status; + fal_execution_status.write.bits.M95_2 = status; + break; + case FAL_EXECUTION_EEPROM_FM24: + fal_execution_status.init.bits.FM24 = status; + fal_execution_status.read.bits.FM24 = status; + fal_execution_status.write.bits.FM24 = status; + break; + default: + DBG_ASSERT(FALSE __DBG_LINE); + break; + } +} + +#if FAL_DBG_ENABLE +// 测试 +static void fal_execution_inspection_test(void) +{ + if (FALSE == fal_execution_kv_write(KEY_CALIBPARA_PARAM, (uint8_t *)&calib_param, (CALIBPARA_NUM * sizeof(calib_param_t)))) + { + fal_execution_status.write.bits.M95_1 = 0; + } + else + { + fal_execution_status.write.bits.M95_1 = 1; + } + + if (FALSE == fal_execution_kv_write(KEY_DEVICE, (uint8_t *)&udevice, sizeof(device_typedef))) + { + fal_execution_status.write.bits.M95_1 = 0; + } + else + { + fal_execution_status.write.bits.M95_1 = 1; + } + + if (FALSE == fal_execution_kv_write(KEY_HART_DEVICE_VARIABLE_PARAM, (uint8_t *)hart_storage_variable, sizeof(hart_storage_variable_t))) + { + fal_execution_status.write.bits.M95_1 = 0; + } + else + { + fal_execution_status.write.bits.M95_1 = 1; + } + + for (uint8_t i = 0; i < 10; i++) + { + get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time); + if (FALSE == fal_execution_kv_write(KEY_REAL_TIME_DATA, (uint8_t *)&rt_data.save, sizeof(rt_save_param_t))) + { + fal_execution_status.write.bits.FM24 = 0; + } + else + { + fal_execution_status.write.bits.FM24 = 1; + } + } +} +#endif + +void fal_execution_inspection(uint16_t cycle) +{ +#if FAL_DBG_ENABLE + fal_execution_inspection_test(); +#else + if (fal_execution_status.init.bits.M95_1 == 1) // M95_1初始化成功,才执行下面的操作 + { + // 校准参数 + { + if (FALSE == fal_execution_data_storage_check(KEY_CALIBPARA_PARAM, (uint8_t *)&calib_param, (CALIBPARA_NUM * sizeof(calib_param_t)))) + { + if (FALSE == fal_execution_kv_write(KEY_CALIBPARA_PARAM, (uint8_t *)&calib_param, (CALIBPARA_NUM * sizeof(calib_param_t)))) + { + fal_execution_status.write.bits.M95_1 = 0; + } + else + { + fal_execution_status.write.bits.M95_1 = 1; + } + return; // 退出 + } + } + + // 设备参数 + { + if (FALSE == fal_execution_data_storage_check(KEY_DEVICE, (uint8_t *)&udevice, sizeof(device_typedef))) + { + if (FALSE == fal_execution_kv_write(KEY_DEVICE, (uint8_t *)&udevice, sizeof(device_typedef))) + { + fal_execution_status.write.bits.M95_1 = 0; + } + else + { + fal_execution_status.write.bits.M95_1 = 1; + } + return; // 退出 + } + } + } + + if (fal_execution_status.init.bits.FM24 == 1) // FM24初始化成功,才执行下面的操作 + { + // 实时数据 + static uint16_t rtdata_cnt = 0; + rtdata_cnt++; + uint32_t save_cycle = udevice.save_cycle * 1000; // ms + uint16_t save_cnt = save_cycle / cycle; + if (rtdata_cnt >= save_cnt) + { + rtdata_cnt = 0; + if (FALSE == fal_execution_data_storage_check(KEY_REAL_TIME_DATA, (uint8_t *)&rt_data.save, sizeof(rt_save_param_t))) + { + get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time); + if (FALSE == fal_execution_kv_write(KEY_REAL_TIME_DATA, (uint8_t *)&rt_data.save, sizeof(rt_save_param_t))) + { + fal_execution_status.write.bits.FM24 = 0; + } + else + { + fal_execution_status.write.bits.FM24 = 1; + } + return; // 退出 + } + } + } +#endif +} diff --git a/User/application/src/key.c b/User/application/src/key.c new file mode 100644 index 0000000..0b9a8fa --- /dev/null +++ b/User/application/src/key.c @@ -0,0 +1,745 @@ +/** + * @file key.c + * @author xxx + * @date 2023-08-29 08:34:41 + * @brief 此文件用于实现按键功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "../inc/key.h" +#include "bsp.h" +#include +#include "sys.h" + +#define INVALID_BUTTON_TICKS 1000 // 无效按键时间 毫秒 + +/* 按钮 */ +struct Button key_1; +struct Button key_2; +struct Button key_3; +struct Button key_4; +struct Button key_5; +struct Button key_6; +struct Button key_auto; + +uint64_t rnd_key_1; +uint64_t rnd_key_2; +uint64_t rnd_key_3; +uint64_t rnd_key_4; +uint64_t rnd_key_5; +uint64_t rnd_key_6; +uint64_t rnd_key_auto; + +// 模拟按键记录 +#define EFFECTIVE_TIME 1000 // 有效时间 毫秒 +static __IO uint32_t key_imitate = 0; +static __IO uint16_t key2_5_imitate_timers = 0; +static uint8_t key_init_flag = 0; +static BOOL key1_done_flag = FALSE; +static BOOL key6_done_flag = FALSE; +static BOOL auto_done_flag = FALSE; +static __IO BOOL long_done_flag = FALSE; +static uint32_t key_start_ticks = 0; // 记录开启时间,仿真的时候按键会有毛刺,在xx秒之后按下有效 + +// 允许执行的条件 +static BOOL allow_condition(void) +{ + /** + * key的初始化在LCD板子上电之前,因为是低电平有效,所以会误判为按键按下 + */ + if (!LCD_IS_POWER_ON() || (sys_millis() - key_start_ticks < INVALID_BUTTON_TICKS)) // 仿真的时候按键会有毛刺,在xx秒之后按下有效 + { + key_imitate = 0; // 清除标志位 + return FALSE; + } + return TRUE; +} + +/** + * @brief 读取按键GPIO电平 + * @param {uint8_t} button_id + * @return {uint8_t} GPIO电平 + * @note + */ +static uint8_t read_button_gpio(uint8_t button_id) +{ + if (allow_condition() == FALSE) + { + return ACTIVE_LEVEL_HIGH; + } + + if (key2_5_imitate_timers > 0) + { + key2_5_imitate_timers--; + } + else + { + key_imitate = 0; + } + + switch (button_id) + { + case KEY1: + return GPIO_READ(KEY1_GPIO_Port, KEY1_Pin); + case KEY2: + return GPIO_READ(KEY2_GPIO_Port, KEY2_Pin); + case KEY3: + return GPIO_READ(KEY3_GPIO_Port, KEY3_Pin); + case KEY4: + return GPIO_READ(KEY4_GPIO_Port, KEY4_Pin); + case KEY5: + return GPIO_READ(KEY5_GPIO_Port, KEY5_Pin); + case KEY6: + return GPIO_READ(KEY6_GPIO_Port, KEY6_Pin); + case KEYAUTO: + return GPIO_READ(KEY_AUTO_GPIO_Port, KEY_AUTO_Pin); + default: + return 0; + } +} + +/** + * @brief key2和key5同时按下判断 + * @return {*} + * @note + */ +static void key_2_5_press_down(void) +{ + __NOP(); + if (allow_condition() == FALSE) + { + return; + } + // 检查标志,判断key2和key5同时按下 + if (key_imitate == (KEY2 | KEY5)) + { + key_imitate = 0; // 清除标志位 +#if LCD_DESIGN == FALSE + menus_jump(MENUS_MAIN, FALSE); // 跳转到主界面 +#else + menus_jump(MENUS_PASSWORD, FALSE); +#endif + } +} + +/** + * @brief 单击1 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_1_press_down_handler(void *btn) +{ + __NOP(); + // 方向0: 按键1->KEY1, 方向180: 按键1->KEY6 + if (get_menus()->dir == 0) + { + menus_key_register(KEY1); // 注册为菜单功能键 + } + else + { + menus_key_register(KEY6); // 注册为菜单功能键 + } +} + +/** + * @brief 双击1 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_1_double_click_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 长按1 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_1_long_press_hold_handler(void *btn) +{ + __NOP(); + long_done_flag = TRUE; + if (key_1.ticks >= (2000 / TICKS_INTERVAL) && key1_done_flag == FALSE) + { + key1_done_flag = TRUE; + __NOP(); + // 跳转到工作界面 + menus_jump(MENUS_WORK, TRUE); + } +} + +/** + * @brief 弹起1 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_1_up_handler(void *btn) +{ + __NOP(); + long_done_flag = FALSE; + key1_done_flag = FALSE; +} + +/** + * @brief 单击2 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_2_press_down_handler(void *btn) +{ + __NOP(); + // 方向0: 按键2->KEY2, 方向180: 按键2->KEY5 + if (get_menus()->dir == 0) + { + key_imitate |= KEY2; // 设置按下标志(组合键) + key2_5_imitate_timers = EFFECTIVE_TIME / TICKS_INTERVAL; // 设置按下时间(组合键) + hart_cache_data_send(rnd_key_2); // 按键测试 + menus_key_register(KEY2); // 注册为菜单功能键 + } + else + { + key_imitate |= KEY5; // 设置按下标志(组合键) + key2_5_imitate_timers = EFFECTIVE_TIME / TICKS_INTERVAL; // 设置按下时间(组合键) + hart_cache_data_send(rnd_key_5); // 按键测试 + menus_key_register(KEY5); // 注册为菜单功能键 + } + // 组合键判断 + key_2_5_press_down(); +} + +/** + * @brief 双击2 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_2_double_click_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 长按2 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_2_long_press_hold_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 弹起2 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_2_up_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 单击3 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_3_press_down_handler(void *btn) +{ + __NOP(); + // 方向0: 按键3->KEY3, 方向180: 按键3->KEY4 + if (get_menus()->dir == 0) + { + hart_cache_data_send(rnd_key_3); // 按键测试 + menus_key_register(KEY3); // 注册为菜单功能键 + } + else + { + hart_cache_data_send(rnd_key_4); // 按键测试 + menus_key_register(KEY4); // 注册为菜单功能键 + } +} + +/** + * @brief 双击3 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_3_double_click_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 长按3 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_3_long_press_hold_handler(void *btn) +{ + __NOP(); + DISABLE_TIM(TIM7); + // 方向0: 按键3->KEY3, 方向180: 按键3->KEY4 + if (get_menus()->dir == 0) + { + menus_key_register(KEY3 | WM_LONG); // 注册为菜单功能键 + menus_key_long_start(); // 开始计时长按时间 + } + else + { + menus_key_register(KEY4 | WM_LONG); // 注册为菜单功能键 + menus_key_long_start(); // 开始计时长按时间 + } +} + +// 弹起3 +static void key_3_up_handler(void *btn) +{ + __NOP(); + ENABLE_TIM(TIM7); + menus_key_long_stop(); // 清除长按时间 +} + +/** + * @brief 单击4 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_4_press_down_handler(void *btn) +{ + __NOP(); + // 方向0: 按键4->KEY4, 方向180: 按键4->KEY3 + if (get_menus()->dir == 0) + { + hart_cache_data_send(rnd_key_4); // 按键测试 + menus_key_register(KEY4); // 注册为菜单功能键 + } + else + { + hart_cache_data_send(rnd_key_3); // 按键测试 + menus_key_register(KEY3); // 注册为菜单功能键 + } +} + +/** + * @brief 双击4 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_4_double_click_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 长按4 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_4_long_press_hold_handler(void *btn) +{ + __NOP(); + DISABLE_TIM(TIM7); + // 方向0: 按键4->KEY4, 方向180: 按键4->KEY3 + if (get_menus()->dir == 0) + { + menus_key_register(KEY4 | WM_LONG); // 注册为菜单功能键 + menus_key_long_start(); // 开始计时长按时间 + } + else + { + menus_key_register(KEY3 | WM_LONG); // 注册为菜单功能键 + menus_key_long_start(); // 开始计时长按时间 + } +} + +/** + * @brief 弹起4 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_4_up_handler(void *btn) +{ + __NOP(); + ENABLE_TIM(TIM7); + menus_key_long_stop(); // 清除长按时间 +} +/** + * @brief 单击5 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_5_press_down_handler(void *btn) +{ + __NOP(); + // 方向0: 按键5->KEY5, 方向180: 按键5->KEY2 + if (get_menus()->dir == 0) + { + key_imitate |= KEY5; // 设置按下标志(组合键) + key2_5_imitate_timers = EFFECTIVE_TIME / TICKS_INTERVAL; // 设置按下时间(组合键) + hart_cache_data_send(rnd_key_5); // 按键测试 + menus_key_register(KEY5); // 注册为菜单功能键 + } + else + { + key_imitate |= KEY2; // 设置按下标志(组合键) + key2_5_imitate_timers = EFFECTIVE_TIME / TICKS_INTERVAL; // 设置按下时间(组合键) + hart_cache_data_send(rnd_key_2); // 按键测试 + menus_key_register(KEY2); // 注册为菜单功能键 + } + // 组合键判断 + key_2_5_press_down(); +} + +/** + * @brief 双击5 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_5_double_click_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 长按5 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_5_long_press_hold_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 弹起5 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_5_up_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 单击6 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_6_press_down_handler(void *btn) +{ + __NOP(); + button_id_e key = KEY0; + // 方向0: 按键6->KEY6, 方向180: 按键6->KEY1 + if (get_menus()->dir == 0) + { + key = KEY6; + } + else + { + key = KEY1; + } + menus_key_register(key); +} + +/** + * @brief 双击6 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_6_double_click_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief 长按6 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_6_long_press_hold_handler(void *btn) +{ + __NOP(); + long_done_flag = TRUE; + if (key_6.ticks >= (2000 / TICKS_INTERVAL) && key6_done_flag == FALSE) + { + key6_done_flag = TRUE; + __NOP(); + // 跳转到菜单界面 + menus_jump(MENUS_MAIN, FALSE); // 跳转到主菜单界面 + } +} + +/** + * @brief 弹起6 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_6_up_handler(void *btn) +{ + __NOP(); + long_done_flag = FALSE; + key6_done_flag = FALSE; +} + +/** + * @brief auto按下 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_auto_press_down_handler(void *btn) +{ + __NOP(); +} + +/** + * @brief auto长按 + * @param {void} *btn + * @return {*} + * @note + */ +static void key_auto_long_press_hold_handler(void *btn) +{ + if (key_auto.ticks >= (3000 / TICKS_INTERVAL) && auto_done_flag == FALSE) + { + auto_done_flag = TRUE; + // 跳转到自动整定界面 + menus_jump(MENUS_SELFTUNE, TRUE); + } +} + +// 弹起auto +static void key_auto_up_handler(void *btn) +{ + __NOP(); + auto_done_flag = FALSE; +} + +/** + * @brief 按键初始化 + * @return {*} + * @note + */ +void key_init(void) +{ + if (key_init_flag == 1) + { + return; + } + key_init_flag = 1; + GPIO_SET_INPUT(KEY1_GPIO_Port, KEY1_Pin); + GPIO_SET_INPUT(KEY2_GPIO_Port, KEY2_Pin); + GPIO_SET_INPUT(KEY3_GPIO_Port, KEY3_Pin); + GPIO_SET_INPUT(KEY4_GPIO_Port, KEY4_Pin); + GPIO_SET_INPUT(KEY5_GPIO_Port, KEY5_Pin); + GPIO_SET_INPUT(KEY6_GPIO_Port, KEY6_Pin); + GPIO_SET_INPUT(KEY_AUTO_GPIO_Port, KEY_AUTO_Pin); + + button_init(&key_1, read_button_gpio, ACTIVE_LEVEL_LOW, KEY1); + button_init(&key_2, read_button_gpio, ACTIVE_LEVEL_LOW, KEY2); + button_init(&key_3, read_button_gpio, ACTIVE_LEVEL_LOW, KEY3); + button_init(&key_4, read_button_gpio, ACTIVE_LEVEL_LOW, KEY4); + button_init(&key_5, read_button_gpio, ACTIVE_LEVEL_LOW, KEY5); + button_init(&key_6, read_button_gpio, ACTIVE_LEVEL_LOW, KEY6); + button_init(&key_auto, read_button_gpio, ACTIVE_LEVEL_LOW, KEYAUTO); + + // 添加按键1按下按钮的按下按钮回调函数 + button_attach(&key_1, PRESS_DOWN, key_1_press_down_handler); + // 添加按键1双击按钮的按下按钮回调函数 + button_attach(&key_1, DOUBLE_CLICK, key_1_double_click_handler); + // 添加按键1长按按钮的按下按钮回调函数 + button_attach(&key_1, LONG_PRESS_HOLD, key_1_long_press_hold_handler); + // 添加按键1按下按钮的抬起按钮回调函数 + button_attach(&key_1, PRESS_UP, key_1_up_handler); + + // 添加按键2按下按钮的按下按钮回调函数 + button_attach(&key_2, PRESS_DOWN, key_2_press_down_handler); + // 添加按键2双击按钮的按下按钮回调函数 + button_attach(&key_2, DOUBLE_CLICK, key_2_double_click_handler); + // 添加按键2长按按钮的按下按钮回调函数 + button_attach(&key_2, LONG_PRESS_HOLD, key_2_long_press_hold_handler); + // 添加按键2按下按钮的抬起按钮回调函数 + button_attach(&key_2, PRESS_UP, key_2_up_handler); + + // 添加按键3按下按钮的按下按钮回调函数 + button_attach(&key_3, PRESS_DOWN, key_3_press_down_handler); + // 添加按键3双击按钮的按下按钮回调函数 + button_attach(&key_3, DOUBLE_CLICK, key_3_double_click_handler); + // 添加按键3长按按钮的按下按钮回调函数 + button_attach(&key_3, LONG_PRESS_HOLD, key_3_long_press_hold_handler); + // 添加按键3按下按钮的抬起按钮回调函数 + button_attach(&key_3, PRESS_UP, key_3_up_handler); + + // 添加按键4按下按钮的按下按钮回调函数 + button_attach(&key_4, PRESS_DOWN, key_4_press_down_handler); + // 添加按键4双击按钮的按下按钮回调函数 + button_attach(&key_4, DOUBLE_CLICK, key_4_double_click_handler); + // 添加按键4长按按钮的按下按钮回调函数 + button_attach(&key_4, LONG_PRESS_HOLD, key_4_long_press_hold_handler); + // 添加按键4按下按钮的抬起按钮回调函数 + button_attach(&key_4, PRESS_UP, key_4_up_handler); + + // 添加按键5按下按钮的按下按钮回调函数 + button_attach(&key_5, PRESS_DOWN, key_5_press_down_handler); + // 添加按键5双击按钮的按下按钮回调函数 + button_attach(&key_5, DOUBLE_CLICK, key_5_double_click_handler); + // 添加按键5长按按钮的按下按钮回调函数 + button_attach(&key_5, LONG_PRESS_HOLD, key_5_long_press_hold_handler); + // 添加按键5按下按钮的抬起按钮回调函数 + button_attach(&key_5, PRESS_UP, key_5_up_handler); + + // 添加按键6按下按钮的按下按钮回调函数 + button_attach(&key_6, PRESS_DOWN, key_6_press_down_handler); + // 添加按键6双击按钮的按下按钮回调函数 + button_attach(&key_6, DOUBLE_CLICK, key_6_double_click_handler); + // 添加按键6长按按钮的按下按钮回调函数 + button_attach(&key_6, LONG_PRESS_HOLD, key_6_long_press_hold_handler); + // 添加按键6按下按钮的抬起按钮回调函数 + button_attach(&key_6, PRESS_UP, key_6_up_handler); + + // 添加按键auto按下按钮的按下按钮回调函数 + button_attach(&key_auto, PRESS_DOWN, key_auto_press_down_handler); + // 添加按键auto长按按钮的按下按钮回调函数 + button_attach(&key_auto, LONG_PRESS_HOLD, key_auto_long_press_hold_handler); + // 添加按键auto按下按钮的抬起按钮回调函数 + button_attach(&key_auto, PRESS_UP, key_auto_up_handler); + + srand((unsigned)sys_millis()); + rnd_key_1 = rand(); + rnd_key_2 = rand(); + rnd_key_3 = rand(); + rnd_key_4 = rand(); + rnd_key_5 = rand(); + rnd_key_6 = rand(); + rnd_key_auto = rand(); + + key_start_ticks = sys_millis(); // 记录开启时间,仿真的时候按键会有毛刺,在xx秒之后按下有效 + + key_botton_start(); +} + +void key_botton_start(void) +{ + button_start(&key_1); + button_start(&key_2); + button_start(&key_3); + button_start(&key_4); + button_start(&key_5); + button_start(&key_6); + button_start(&key_auto); +} + +/** + * @brief 按键反初始化 + * @return {*} + * @note + */ +void key_dinit(void) +{ + if (key_init_flag == 1) + { + key_init_flag = 0; + button_stop(&key_1); + button_stop(&key_2); + button_stop(&key_3); + button_stop(&key_4); + button_stop(&key_5); + button_stop(&key_6); + button_stop(&key_auto); + GPIO_SET_ANALOG(KEY1_GPIO_Port, KEY1_Pin); + GPIO_SET_ANALOG(KEY2_GPIO_Port, KEY2_Pin); + GPIO_SET_ANALOG(KEY3_GPIO_Port, KEY3_Pin); + GPIO_SET_ANALOG(KEY4_GPIO_Port, KEY4_Pin); + GPIO_SET_ANALOG(KEY5_GPIO_Port, KEY5_Pin); + GPIO_SET_ANALOG(KEY6_GPIO_Port, KEY6_Pin); + GPIO_SET_ANALOG(KEY_AUTO_GPIO_Port, KEY_AUTO_Pin); + } +} + +/** + * @brief 获取按键uuid + * @param {button_id_e} k - 按键实体句柄 + * @return {uint64_t} 按键uuid + * @note + */ +uint64_t get_key_uuid(button_id_e k) +{ + uint64_t uuid = 0; + switch (k) + { + case KEY1: + uuid = rnd_key_1; + break; + case KEY2: + uuid = rnd_key_2; + break; + case KEY3: + uuid = rnd_key_3; + break; + case KEY4: + uuid = rnd_key_4; + break; + case KEY5: + uuid = rnd_key_5; + break; + case KEY6: + uuid = rnd_key_6; + break; + case KEY_AUTO: + uuid = rnd_key_auto; + break; + default: + break; + } + + return uuid; +} + +/** + * @brief 清除按键HART缓存区 + * @return {*} + * @note + */ +void remove_key_hart_cache(void) +{ + hart_cache_remove(get_key_uuid(KEY1)); + hart_cache_remove(get_key_uuid(KEY2)); + hart_cache_remove(get_key_uuid(KEY3)); + hart_cache_remove(get_key_uuid(KEY4)); + hart_cache_remove(get_key_uuid(KEY5)); + hart_cache_remove(get_key_uuid(KEY6)); + hart_cache_remove(get_key_uuid(KEYAUTO)); +} + +/** + * @brief 获取按键长按状态 + * @return {*} + * @note + */ +BOOL key_long_press_flag(void) +{ + return long_done_flag; +} diff --git a/User/application/src/params.c b/User/application/src/params.c new file mode 100644 index 0000000..81bc3a6 --- /dev/null +++ b/User/application/src/params.c @@ -0,0 +1,346 @@ +/** + * @file params.c + * @author xxx + * @date 2023-08-30 08:58:43 + * @brief 此文件定义了板卡全部重要参数(设备参数+校准参数),以及参数管理配置功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "../inc/params.h" +#include "board.h" +#include "delay.h" +#include "diagnosis.h" +#include "fal_execution.h" +#include "test_bsp.h" +#include + +#define CURRENT_VERSION (HW_VER << 16 | SW_VER << 8 | FW_VER) + +/// 磁条规格 [0]:最小值 [1]:最大值 +const uint16_t magnet_param_table[MAGNET_PARAM_MAX][2] = + { + // 0位成员用于测试 + {0, 10}, + {0, 100}, +}; + +/// 气压传感规格 [0]:最小值 [1]:最大值 +const uint16_t pressure_param_table[PRESSURE_PARAM_MAX][2] = + { + {100, 4000}, // 气源 + {100, 4000}, // A + {100, 4000}, // B +}; + +/// 阀门流量特性表 +const uint16_t valve_characteristics_table[][17] = + { + // 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + // 线性 + {0, 625, 1250, 1875, 2500, 3125, 3750, 4375, 5000, 5625, 6250, 6875, 7500, 8125, 8750, 9375, 10000}, + + // 等百分比1(1:50) + {0, 255, 326, 416, 532, 679, 867, 1107, 1414, 1806, 2306, 2945, 3761, 4802, 6132, 7831, 10000}, + + // 快开(50:1) + {0, 255, 326, 416, 532, 679, 867, 1107, 1414, 1806, 2306, 2945, 3761, 4802, 6132, 7831, 10000}, + + // 等百分比1(1:25) + {0, 255, 326, 416, 532, 679, 867, 1107, 1414, 1806, 2306, 2945, 3761, 4802, 6132, 7831, 10000}, + + // 快开(25:1) + {0, 255, 326, 416, 532, 679, 867, 1107, 1414, 1806, 2306, 2945, 3761, 4802, 6132, 7831, 10000}, + + // 等百分比2(1:33) + {0, 131, 281, 454, 655, 892, 1173, 1476, 1826, 2258, 2793, 3455, 4273, 5285, 6537, 8085, 10000}, + + // 快开(33:1) + {0, 2913, 4684, 5721, 6456, 7027, 7493, 7887, 8228, 8529, 8799, 9042, 9265, 9469, 9659, 9835, 10000}, +}; + +/** + * @brief 参数初始化 + * @return {*} + * @note + */ +void params_init(void) +{ + BOOL res = FALSE; + driver_icon_enable.dev = 0; // 图标变量 + + // 清除数据内存 + osel_memset((uint8_t *)&udevice, 0, sizeof(device_typedef)); + osel_memset((uint8_t *)&rt_data, 0, sizeof(real_time_data_t)); + osel_memset((uint8_t *)&calib_param, 0, (CALIBPARA_NUM * sizeof(calib_param_t))); + osel_memset((uint8_t *)&mode_params, 0, sizeof(mode_params_t)); + + // 读EEPROM内的设备参数 + res = fal_execution_kv_read(KEY_DEVICE, (uint8_t *)&udevice, sizeof(device_typedef)); + if (udevice.dev_version != CURRENT_VERSION) + { + params_restart(); + hart_attribute_params_restart(); + } + set_app_preload_language_flag(udevice.display_language); + + // 读EEPROM内的校准参数 + res = fal_execution_kv_read(KEY_CALIBPARA_PARAM, (uint8_t *)&calib_param, (CALIBPARA_NUM * sizeof(calib_param_t))); + if (res == FALSE) + { + __NOP(); // 异常已经在fal_execution_kv_read函数内处理,此处不做处理 + } + + // 读取FM24内的实时参数 + res = fal_execution_kv_read(KEY_REAL_TIME_DATA, (uint8_t *)&rt_data.save, sizeof(rt_save_param_t)); + if (res == FALSE) + { + if (TRUE == fal_execution_kv_write(KEY_REAL_TIME_DATA, (uint8_t *)&rt_data.save, sizeof(rt_save_param_t))) + { + fal_execution_status_set(FAL_EXECUTION_EEPROM_FM24, TRUE); + } + else + { + fal_execution_status_set(FAL_EXECUTION_EEPROM_FM24, FALSE); + } + } + + // 读取模式参数 + res = fal_execution_kv_read(KEY_MODE_PARAM, (uint8_t *)&mode_params, sizeof(mode_params_t)); + if (res == FALSE) + { + osel_memset((uint8_t *)&mode_params, 0, sizeof(mode_params_t)); + } + // 上电增加累计次数 + rt_data.save.power_on_cnt++; + // HART参数映射 + hart_attribute_params_map(); +} + +/** + * @brief 参数恢复出厂设置 + * @return {*} + * @note + */ +void params_restart(void) +{ + uint8_t i = 0; + + // 清除数据内存 + osel_memset((uint8_t *)&udevice, 0, sizeof(device_typedef)); + osel_memset((uint8_t *)&rt_data, 0, sizeof(real_time_data_t)); + osel_memset((uint8_t *)&calib_param, 0, (CALIBPARA_NUM * sizeof(calib_param_t))); + + /*************************************** 设备参数 ***************************************/ + // 定位器版本号 + udevice.dev_version = CURRENT_VERSION; + // 定位器硬件版本号 + udevice.dev_hw_version = HW_VER; + // 定位器软件版本号 + udevice.dev_fw_version = SW_VER; + // 定位器输出模式 + udevice.dev_algorithm_mode = MODE_FREQUENCY_DOMAIN_CONTROL_ALGORITHM; + // 定位器型号 + udevice.dev_model = POSITIONER_MODEL_GPS3001; + // 执行机构行程类型:直行程/角行程 TRAVEL_TYPE_STRAIGHT/TRAVEL_TYPE_ANGULAR + udevice.value_travel_type = TRAVEL_TYPE_STRAIGHT; + // 执行机构气动类型:气开/气关 ATO/ATC + udevice.value_action_type = ATO; + // 执行机构作用类型:单作用/双作用 + udevice.value_relay_type = VALVE_ACTING_SINGLE; + + osel_memset((uint8_t *)&udevice.dev_serial_num, 0, INST_SERIAL_NUM_LEN); + + // 定位器作用方向:正作用/反作用 + udevice.dev_driver_dir = CONTROLLER_ACTING_NORMAL; + // 定位器安装方向 + udevice.dev_install_dir = CONTROLLER_INSTALL_NORMAL; + // 定位器工作模式 + udevice.dev_work_mode = ON_LINE_MODE; + // 定位器控制模式:位置控制/压力控制 + udevice.dev_ctrl_mode = POS_CTRL_MODE; + // 执行机构类型 + udevice.value_type = VALUE_TYPE_OTHER; + // 执行机构尺寸 + udevice.valve_size = VALUE_SIZE_OTHER; + // 执行机构行程 + // 直行程:16mm、25mm、40mm、60mm、100mm、130mm、160mm、200mm + // 角行程:0~60°、0~90° + udevice.value_travel = VALUE_TRAVEL_OTHER; + // 自定义执行机构行程 + udevice.self_value_travel = 0; + // 阀门特性 + udevice.valve_chart = VALVE_CHARACT_LINEAR; + // 自定义阀门特性 + for (i = 0; i < 17; i++) + udevice.self_value_chart[i] = 0; + // 磁条规格 + udevice.magnet_spec = MAGNET_SPAC_TEST; + // 写入保护禁用/使能 + udevice.write_protect_enable = FALSE; + // 压力传感器禁用/使能 + udevice.press_sensor_enable = TRUE; + // 增速器禁用/使能 + udevice.speed_increaser_enable = FALSE; + // 快排阀禁用/使能 + udevice.quick_exhaust_enable = FALSE; + // 无线通讯禁用/使能 + udevice.wireless_enable = TRUE; + // PWM输出电流禁用/使能 + udevice.output_current_enable = FALSE; + // 输出开关触发逻辑 + udevice.swo_logic[0] = TRIGGER_LOGIC_DISABLE; + udevice.swo_logic[1] = TRIGGER_LOGIC_DISABLE; + // 输出开关触发位置 + udevice.swo_value[0] = 0; + udevice.swo_value[1] = 0; + // 显示方向 0/180 + udevice.display_direction = DISP_DIR_0; + // 显示语言 + udevice.display_language = CHINESE; // CHINESE; + // 行程百分比显示方式 + udevice.display_travel_mode = TRAVEL_DISPLAY_NORMAL; + // 报警处理模式 + udevice.alarm_handle_mode = ALARM_HANDLING_CONTINUE; + // 复位处理模式 + udevice.reset_handle_mode = RESET_HANDLING_CONTINUE; + // 温度单位 + udevice.temperature_unit = TEMPERATURE_UNIT_C; + // 电流单位 + udevice.current_unit = CURRENT_UNIT_MA; + // 行程单位 + udevice.travel_unit = TRAVEL_UNIT_PRE; + // 压力单位 + udevice.press_unit = PRESSURE_UNIT_Kpa; + // 力学单位(摩擦力/弹簧力) + udevice.force_unit = FORCE_UNIT_N; + + // 阀门打开(上行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec] + udevice.travel_rate_open = 0; + // 阀门关闭(下行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec] + udevice.travel_rate_close = 0; + // 阀门全开时间 + udevice.all_open_time = 0; + // 阀门全关时间 + udevice.all_close_time = 0; + // 阀门0位置行程反馈ADC值 + udevice.pos0_travel_vol = 0; + // 阀门100位置行程反馈ADC值 + udevice.pos100_travel_vol = 0; + // 阀门0位置小回路反馈ADC值 + udevice.pos0_minor_vol = 0; + // 阀门100位置小回路反馈ADC值 + udevice.pos100_minor_vol = 0; + // 阀门0位置A路气压反馈ADC值 + udevice.pos0_press_a_vol = 0; + // 阀门100位置A路气压反馈ADC值 + udevice.pos100_press_a_vol = 0; + // 阀门0位置B路气压反馈ADC值 + udevice.pos0_press_b_vol = 0; + // 阀门100位置B路气压反馈ADC值 + udevice.pos100_press_b_vol = 0; + // 记录存储间隔时间 + udevice.save_cycle = 5; + // 配置时间 + udevice.operating_time = 0; + // 死区(%),表示在目标位置附近设置的可允许偏差。若阀门填料的摩擦力较大,可相应调整并设置此数值, + // 以防止因摩擦导致循环受限。若死区设置为0.5%,则其对应范围为目标的±0.5%。 + udevice.travel_dead = 0.3; // 0.2% + + // 输入范围低4-19mA (2位小数,如 4mA = 4.00,20mA = 20.00) + udevice.input_lower = 4.00; + // 输入范围高5-20mA (2位小数,如 4mA = 4.00,20mA = 20.00) + udevice.input_upper = 20.00; + // 温度报警上限 + udevice.temp_upper = 80; + // 温度报警下限 + udevice.temp_lower = -50; + // 供应压力报警上限 + udevice.supply_upper = 0; + // 供应压力报警下限 + udevice.supply_lower = 0; + // 摩擦力报警上限 + udevice.friction_upper = 0; + // 摩擦力报警下限 + udevice.friction_lower = 0; + // 弹簧力报警上限 + udevice.elasticity_upper = 0; + // 弹簧力报警下限 + udevice.elasticity_lower = 0; + // 行程范围上限 + udevice.travel_upper = 95; + // 行程范围下限 + udevice.travel_lower = 5; + // 行程报警死区 + udevice.travel_alert_dead = 0.5; + // 小信号切除禁用/使能 + udevice.travel_cut_enable = TRUE; + // 小信号切除上限 + udevice.travel_cut_upper = 99.5; + // 小信号切除下限 + udevice.travel_cut_lower = 0.5; + // 分程控制禁用/使能 + udevice.part_travel_enable = FALSE; + // 分程控制上限 + udevice.part_travel_upper = 0; + // 分程控制下限 + udevice.part_travel_lower = 0; + // 累计行程上限 + udevice.travel_sum_upper = 0xFFFFFFFF; + // 累计行程死区:行程超过累计行程死区时,计算累计行程 + udevice.travel_sum_dead = 5; + // 动作次数上限 + udevice.act_sum_upper = 0xFFFFFFFF; + // 动作次数死区:行程超过动作次数死区时,计算动作次数 + udevice.act_sum_dead = 5; + // 输入的额定气源压力,单位:kpa + udevice.supply_press = 360.0; + // 气源偏差范围±% + udevice.supply_error = 10; + // 报警等待时间(秒)(偏差超出范围的持续时间上限) + udevice.supply_error_time = 10; + // 参考电压 + udevice.vref = 3.0; + // 参考电压偏差 + udevice.vref_error = 0.3; + // 参考电压报警等待时间 + udevice.vref_error_time = 1; + // 行程偏差报警点±% + udevice.travel_error = 10; + // 行程偏差报警等待时间(秒)(偏差超出范围的持续时间上限) + udevice.travel_error_time = 10; + // 驱动阀门动作所需上限值 + udevice.output_max = 4095; + // 驱动阀门动作所需下限值 + udevice.output_min = 0; + // 整定标志 + udevice.tuned_flag = TUNED_NONE; + // PID参数选择 + udevice.pid_index = Adaptive_PID; + // 自适应PID参数 + udevice.apid_kp = 1; + udevice.apid_ki = 0.05f; + udevice.apid_kd = 0; + udevice.apid_dead = 0.3; + // 自定义PID参数 + udevice.spid_kp = 1; + udevice.spid_ki = 0; + udevice.spid_kd = 0; + udevice.spid_dead = 0.3; + // PWM输出电流原始值 + udevice.output_4ma_duty = 546; + udevice.output_20ma_duty = 2730; + osel_memset((uint8_t *)&udevice.menus_main_password, 0, PASSWORD_LEN); + + /*************************************** 校准参数 ***************************************/ + // 回路电流 + calib_param[CALIBPARA_LOOP].value[0] = 0.611153543; + calib_param[CALIBPARA_LOOP].value[1] = 2.1390624; + + // 4~20ma PWM输出校准 + set_pwm_calib_current(); + + // 立即保存 + fal_execution_kv_write(KEY_CALIBPARA_PARAM, (uint8_t *)&calib_param, (CALIBPARA_NUM * sizeof(calib_param_t))); + fal_execution_kv_write(KEY_DEVICE, (uint8_t *)&udevice, sizeof(device_typedef)); + fal_execution_kv_write(KEY_REAL_TIME_DATA, (uint8_t *)&rt_data.save, sizeof(rt_save_param_t)); +} diff --git a/User/application/src/params_hart.c b/User/application/src/params_hart.c new file mode 100644 index 0000000..3df7693 --- /dev/null +++ b/User/application/src/params_hart.c @@ -0,0 +1,21 @@ +#include "../inc/params.h" +#include "board.h" +#include "delay.h" +#include "diagnosis.h" +#include "fal_execution.h" +#include + +void hart_attribute_params_map(void) +{ + +} + +/** + * @brief HART设备参数初始化 + * @return {*} + * @note + */ +void hart_attribute_params_restart(void) +{ + +} diff --git a/User/application/src/pdctrl.c b/User/application/src/pdctrl.c new file mode 100644 index 0000000..833b199 --- /dev/null +++ b/User/application/src/pdctrl.c @@ -0,0 +1,310 @@ +#include "pdctrl.h" +#include "main.h" +#include "entity.h" +#include "leds.h" +#include "board.h" +pdctrl_t pdctrl_data; + +__IO static pdctrl_mode_e out_mode = PDCTRL_DAC; +__IO static BOOL pdctrl_run_flag = FALSE; + +static void dac_dinit(void) +{ + DAC_STOP(DAC, PDCTRL_DAC_CHINNEL); // DAC通道禁用 + GPIO_SET_ANALOG(PDCTRL_DAC_GPIO_Port, PDCTRL_DAC_Pin); +} + +static void dac_init(void) +{ + pdctrl_data.last_out = 0xffff; + + GPIO_SET_ANALOG(PDCTRL_DAC_GPIO_Port, PDCTRL_DAC_Pin); + DAC_START(DAC, PDCTRL_DAC_CHINNEL); // DAC通道使能 +} + +static void pwm_dinit(void) +{ + PWM_STOP(PDCTRL_PWM_TIM, PDCTRL_PWM_CHINNEL); // PWM通道禁用 + GPIO_SET_ANALOG(PDCTRL_PWM_GPIO_Port, PDCTRL_PWM_Pin); +} + +static void pwm_init(void) +{ + pdctrl_data.last_out = 0xffff; + GPIO_SET_ALTERNATE(PDCTRL_PWM_GPIO_Port, PDCTRL_PWM_Pin); + if (pdctrl_data.pwm_arr_default == 0) + { + pdctrl_data.pwm_arr_default = LL_TIM_GetAutoReload(PDCTRL_PWM_TIM); + } + + PWM_START(PDCTRL_PWM_TIM, PDCTRL_PWM_CHINNEL); // PWM通道使能 +} + +static void pwmp_dinit(void) +{ + PWM_STOP(PDCTRL_PWMP_TIM, PDCTRL_PWMP_CHINNEL); // PWM通道禁用 + GPIO_SET_ANALOG(PDCTRL_PWMP_GPIO_Port, PDCTRL_PWMP_Pin); +} + +static void pwmp_init(void) +{ + pdctrl_data.last_out = 0xffff; + GPIO_SET_ALTERNATE(PDCTRL_PWM_GPIO_Port, PDCTRL_PWM_Pin); + PWM_START(PDCTRL_PWMP_TIM, PDCTRL_PWMP_CHINNEL); // PWM通道使能 +} + +/** + * @brief 控制初始化 + * @param {pdctrl_mode_e} mode + * @param {uint8_t} pwm_frequency + * @return {*} + * @note + */ +void pdctrl_init(pdctrl_mode_e mode) +{ + out_mode = mode; + pdctrl_data.pwm_wid = PWM_WID; + osel_memset((uint8_t *)&pdctrl_data, 0, sizeof(pdctrl_t)); + VIP_H_EN_DISABLE(); + dac_dinit(); + pwm_dinit(); + pwmp_dinit(); + + if (out_mode == PDCTRL_DAC) + { + dac_init(); + } + else if (out_mode == PDCTRL_PWM) + { + pwm_init(); + } + else if (out_mode == PDCTRL_PWMP) + { + pwmp_init(); + } + else + { + return; + } +} + +/** + * @brief 控制停止 + * @return {*} + * @note + */ +void pdctrl_stop(void) +{ + pdctrl_run_flag = FALSE; + if (out_mode == PDCTRL_DAC) + { + dac_dinit(); + } + else if (out_mode == PDCTRL_PWM) + { + pwm_dinit(); + } + else if (out_mode == PDCTRL_PWMP) + { + pwmp_dinit(); + } + else + { + return; + } +} + +/** + * @brief 控制运行 + * @return {*} + * @note + */ +void pdctrl_run(void) +{ + pdctrl_run_flag = TRUE; + if (out_mode == PDCTRL_DAC) + { + dac_init(); + } + else if (out_mode == PDCTRL_PWM) + { + pwm_init(); + } + else if (out_mode == PDCTRL_PWMP) + { + pwmp_init(); + } + else + { + return; + } +} + +/** + * @brief 获取控制器 + * @return {*} + * @note + */ +pdctrl_t *pdctrl_get(void) +{ + return &pdctrl_data; +} + +/** + * @brief 占空比转换为CCR值 + * @param {float32} out + * @return {*} + * @note + */ +uint16_t pdctrl_pwm_duty_convert_ccr(float32 pwm_duty) +{ + return (pwm_duty * pdctrl_data.pwm_arr_default) / 100; +} + +// 计算频率 +static void calculate_pwm_freq(uint32_t arr) +{ + pdctrl_data.sysclk = SystemCoreClock / 1000; + pdctrl_data.psc = LL_TIM_GetPrescaler(PDCTRL_PWM_TIM); + pdctrl_data.freq = (float32)pdctrl_data.sysclk / (float32)(pdctrl_data.psc + 1) / (float32)arr; +} + +/** + * @brief 变频计算占空比 + * @param {uint32_t} arr 自动加载值 + * @return {*} + * @note + */ +uint16_t calculate_pwm_duty(uint32_t arr) +{ + float32 wid = pdctrl_data.pwm_wid; + calculate_pwm_freq(arr); + if (arr < pdctrl_data.pwm_arr_default) + { + wid = (pdctrl_data.pwm_arr_default - arr) * 10 / pdctrl_data.pwm_arr_default + wid; + } + + pdctrl_data.arr_us = 1000.0f / pdctrl_data.freq; + pdctrl_data.duty_percent = ((float32)wid * 100.0f) / pdctrl_data.arr_us; + uint16_t duty = arr * pdctrl_data.duty_percent / 100; + return duty; +} + +/** + * @brief 设置PWM频率 + * @param {uint32_t} freq + * @return {*} + * @note + */ +void pdctrl_set_pwm_wid(uint16_t wid) +{ + pdctrl_data.pwm_wid = wid; +} + +/** + * @brief 动态修改频率 + * @param {uint32_t} arr 自动加载值 + * @return {*} + * @note + */ +void pdctrl_pwm_set_arr(uint32_t arr) +{ + uint16_t pwm_arr = LL_TIM_GetAutoReload(PDCTRL_PWM_TIM); + if (pwm_arr == arr) + { + return; + } + if (arr == 0) + { + arr = pdctrl_data.pwm_arr_default; + } + if (arr > pdctrl_data.pwm_arr_default) + { + // arr = pdctrl_data.pwm_arr_default; + pdctrl_data.pwm_arr_default = arr; + } + LL_TIM_SetAutoReload(PDCTRL_PWM_TIM, arr); + + uint16_t duty = calculate_pwm_duty(arr); + +#if PDCTRL_PWM_CHINNEL == LL_TIM_CHANNEL_CH4 + PWM_SET_DUTY(PDCTRL_PWM_TIM, 4, duty); +#else +#error "PDCTRL_PWM_CHINNEL undefined" +#endif +} + +/** + * @brief 获取占空比 + * @param {uint32_t} arr 自动加载值 + * @return {*} + * @note + */ +float32 pdctrl_pwm_get_duty_percent(uint32_t arr) +{ + calculate_pwm_duty(arr); + return pdctrl_data.duty_percent; +} + +/** + * @brief 控制输出 + * @param {uint16_t} out + * @return {*} + * @note + */ +void pdctrl_out(uint16_t out) +{ + if (pdctrl_run_flag == FALSE) + { + return; + } + + if (pdctrl_data.last_out == out && (pdctrl_data.sysclk == (SystemCoreClock / 1000))) + { + return; + } + + pdctrl_data.last_out = out; + rt_data.ip_output = out; + + if (out_mode == PDCTRL_DAC) + { + DAC_OUT(DAC, PDCTRL_DAC_CHINNEL, out); + } + else if (out_mode == PDCTRL_PWM) + { + pdctrl_pwm_set_arr(out); + } + else if (out_mode == PDCTRL_PWMP) + { +#if PDCTRL_PWMP_CHINNEL == LL_TIM_CHANNEL_CH4 + PWM_SET_DUTY(PDCTRL_PWMP_TIM, 4, out); +#else +#error "PDCTRL_PWMP_CHINNEL undefined" +#endif + } + else + { + return; + } +} + +/** + * @brief 获取控制模式 + * @return {*} + * @note + */ +uint8_t get_pdctrl_mode(void) +{ + return out_mode; +} + +/** + * @brief 获取PWM默认频率 + * @return {*} + * @note + */ +uint16_t get_pwm_arr_default(void) +{ + return pdctrl_data.pwm_arr_default; +} diff --git a/User/board/inc/board.h b/User/board/inc/board.h new file mode 100644 index 0000000..32e966f --- /dev/null +++ b/User/board/inc/board.h @@ -0,0 +1,182 @@ +/** + * @file board.h + * @author xxx + * @date 2023-08-30 14:05:55 + * @brief 头文件 board.h + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __BOARD_H__ +#define __BOARD_H__ +#include "main.h" +#include "bsp.h" +#include "tim.h" +#include "menu.h" +#include "rtc_rx8010.h" +#include "eeprom_m95.h" +#include "eeprom_fm24.h" +#include "eeprom_lc02b.h" +#include "ntc_3950.h" +#include "leds.h" + +#define APP_PRELOAD_AREA 0x10007FF0 ///< 预加载区域 +#define VREF_VALUE 3000 ///< 参考电压mV +#define FONT_TYPE FONT_0816 ///< 字体类型 + +#ifndef ADC_MAX +#define ADC_MAX 4095 //< ADC最大 +#endif +#ifndef DAC_MAX +#define DAC_MAX 4095 //< DAC最大 +#endif + +#define BLE_EN_ENABLE() GPIO_SET(BLE_PWR_GPIO_Port, BLE_PWR_Pin) ///< 蓝牙使能 +#define BLE_EN_DISABLE() GPIO_RESET(BLE_PWR_GPIO_Port, BLE_PWR_Pin) ///< 蓝牙禁用 +#define BLE_IS_ENABLE() (GPIO_READ(BLE_PWR_GPIO_Port, BLE_PWR_Pin) == SET) ///< 蓝牙使能状态 + +#define LCD_DMA DMA1 ///< LCD DMA +#define LCD_DMA_TX_CHANNEL LL_DMA_CHANNEL_5 ///< LCD DMA发送通道 +#define LCD_POWER_ON() GPIO_SET(LCD_PWR_GPIO_Port, LCD_PWR_Pin) ///< LCD电源使能 +#define LCD_POWER_OFF() GPIO_RESET(LCD_PWR_GPIO_Port, LCD_PWR_Pin) ///< LCD电源禁用 +#define LCD_IS_POWER_ON() (GPIO_READ(LCD_PWR_GPIO_Port, LCD_PWR_Pin) == SET) ///< LCD电源使能状态 +#define LCD_DETECT() (0) ///< LCD检测,高电平没有接入,低电平接入 + +#define BP_S_POWER_ON() GPIO_SET(BP_S_PWR_GPIO_Port, BP_S_PWR_Pin) +#define BP_S_POWER_OFF() GPIO_RESET(BP_S_PWR_GPIO_Port, BP_S_PWR_Pin) +#define BP_S_IS_POWER_ON() (GPIO_READ(BP_S_PWR_GPIO_Port, BP_S_PWR_Pin) == SET) + +#define BP_A_POWER_ON() GPIO_SET(BP_A_PWR_GPIO_Port, BP_A_PWR_Pin) +#define BP_A_POWER_OFF() GPIO_RESET(BP_A_PWR_GPIO_Port, BP_A_PWR_Pin) +#define BP_A_IS_POWER_ON() (GPIO_READ(BP_A_PWR_GPIO_Port, BP_A_PWR_Pin) == SET) + +#define BP_B_POWER_ON() GPIO_SET(BP_B_PWR_GPIO_Port, BP_B_PWR_Pin) +#define BP_B_POWER_OFF() GPIO_RESET(BP_B_PWR_GPIO_Port, BP_B_PWR_Pin) +#define BP_B_IS_POWER_ON() (GPIO_READ(BP_B_PWR_GPIO_Port, BP_B_PWR_Pin) == SET) + +/// 禁用 I/P 电流输出 0-6.2V +#define VIP_H_EN_DISABLE() \ + do \ + { \ + GPIO_RESET(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin); \ + GPIO_SET_ANALOG(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin); \ + } while (0) + +/// 使能 I/P 电流输出 0-6.2V +#define VIP_H_EN_ENABLE() \ + do \ + { \ + GPIO_SET_OUTPUT(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin); \ + GPIO_SET(IP_H_PWR_GPIO_Port, IP_H_PWR_Pin); \ + } while (0) + +// PWM对外输出 +#define PWM_CTRL_OUTPUT(out) PWM_SET_DUTY(TIM3, 3, out) + +/* HART */ +#define HART_EN_ENABLE() GPIO_SET(HART_PWR_GPIO_Port, HART_PWR_Pin) ///< HART使能 +#define HART_EN_DISABLE() GPIO_RESET(HART_PWR_GPIO_Port, HART_PWR_Pin) ///< HART禁用 +#define HART_IS_ENABLE() (GPIO_READ(HART_PWR_GPIO_Port, HART_PWR_Pin) == SET) ///< HART使能状态 + +#define HART_RST_ON() GPIO_SET(HART_RST_GPIO_Port, HART_RST_Pin) +#define HART_RST_OFF() GPIO_RESET(HART_RST_GPIO_Port, HART_RST_Pin) +#define HART_RTS_ON() GPIO_SET(HART_RTS_GPIO_Port, HART_RTS_Pin) +#define HART_RTS_OFF() GPIO_RESET(HART_RTS_GPIO_Port, HART_RTS_Pin) +/* HART */ + +/* SWO */ +#define SWO1_OPEN() GPIO_SET(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 开 +#define SWO1_CLOSE() GPIO_RESET(SWO1_GPIO_Port, SWO1_Pin) ///< SWO1 关 +#define SWO2_OPEN() GPIO_SET(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 开 +#define SWO2_CLOSE() GPIO_RESET(SWO2_GPIO_Port, SWO2_Pin) ///< SWO2 关 + +typedef enum +{ + FILTER_AVERAGE = 1, + FILTER_MEDIAN, +} filter_e; + +typedef enum +{ + BOARD_CACHE_1 = 0, + BOARD_CACHE_2, + BOARD_CACHE_MAX, +} board_cache_e; + +typedef enum +{ + // 不需要跳转到bootload + APP_PRELOAD_BOOTLOAD_JUMP_NONE = 0, + // 更新完成等待用户通知跳转到bootload + APP_PRELOAD_BOOTLOAD_JUMP_WAIT = 1, + // 更新完成立即跳转到bootload + APP_PRELOAD_BOOTLOAD_JUMP_IMMEDIATELY, +} app_preload_bootload_jump_e; ///< 预加载BOOTLOAD跳转标志 + +extern const uint32_t NTC_100K_B3950_List[]; +extern __IO uint8_t app_preload_flag; ///< 预加载标志位 +extern __IO uint8_t app_preload_language_flag; ///< 语言标志位 +extern __IO uint8_t app_preload_bootload_flag; ///< 触发BOOTLOAD启动标志(在用户代码中接受代码文件) +extern __IO uint8_t app_preload_bootload_jump_flag; ///< 触发BOOTLOAD跳转标志(在用户代码中接受代码文件) +extern __IO uint32_t app_preload_cupid_encrypt; ///< CPU加密值 + +extern void board_init(void); ///< 板卡初始化 +extern void board_dinit(void); ///< 板卡反初始化 +extern void board_work_stop_or_run(void); ///< 板卡工作停止或运行 +extern void board_cache_reset(void); ///< 板卡缓存复位 +extern uint16_t board_cache_get(board_cache_e index); ///< 板卡缓存获取 +extern void driver_init(void); ///< 功耗引脚初始化 +extern void driver_dinit(void); ///< 功耗引脚反初始化 +extern void lcd_init(void); ///< LCD初始化 +extern void lcd_dinit(void); ///< LCD反初始化 +extern void system_clock_config_set_flag(BOOL flag); ///< 设置系统时钟配置标志 +extern void system_clock_config_low(void); ///< 系统时钟配置低频 +extern void system_clock_config_hight(void); ///< 系统时钟配置高频 +extern void gui_flush(void); ///< LCD刷新 +extern void gui_flush_Clear(void); ///< LCD刷新并清屏 +extern void gui_clr(void); ///< 清屏 +extern void gui_full(void); ///< 全屏黑色 +extern void gui_open(void); ///< 打开GUI +extern void gui_close(void); ///< 关闭GUI +extern void gui_set_scandir(uint8_t dir); ///< 设置扫描方向 +extern void gui_set_clear_flag(void); ///< 设置清屏标志 +extern BOOL gui_get_clear_flag(void); ///< 获取清屏标志 + +extern uint16_t get_dac(float32 output); ///< 根据目标行程计算DAC输出理论值 +extern void pwm_output_position(float32 position_per); ///< PWM输出阀位百分比 +extern void calib_loop(void); ///< 校准回路电流 +extern void calib_kpa(void); ///< 校准压力 +extern void calib_pwm_out(void); ///< 校准PWM输出 +extern void calib_parapos_perent(void); ///< 校准阀门位置参数 +extern uint16_t get_actual_travel_adc_average(void); ///< 获取当前实际行程ADC值 +extern uint16_t get_actual_travel_adc(void); ///< 获取当前实际行程ADC值 +extern float32 get_actual_travel(filter_e filter); ///< 获取当前实际行程 +extern float32 get_actual_travel_2(filter_e filter); ///< 获取当前实际行程 +extern float32 get_current(void); ///< 获取当前回路电流 +extern float32 get_current_deal(float32 current); ///< 获取当前回路电流 +extern float32 get_temperature(void); ///< 获取当前温度值 +extern float32 get_pressure(pressure_index_e id); ///< 获取当前压力 +extern float32 get_flow(void); ///< 获取当前流量 +extern void get_timestamp(uDateTime_TypeDef *time); ///< 获取时间戳 +extern void get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec); ///< 获取实时时间 +extern void set_real_time(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec); +extern BOOL get_app_preload_bootload_flag(void); ///< 获取预加载BOOTLOAD标志位 +extern app_preload_bootload_jump_e get_app_preload_bootload_jump_flag(void); ///< 获取预加载BOOTLOAD跳转标志 +extern void set_pwm_calib_current(void); ///< 设置输出PWM校准电流 +extern void set_loop_4ma(void); ///< 设置回路电流4mA +extern void set_loop_20ma(void); ///< 设置回路电流20mA +extern void set_200kpa(void); ///< 设置200kpa +extern void set_400kpa(void); ///< 设置400kpa +extern void set_output_4ma_pwm(uint16_t value); ///< 设置输出4mA时的PWM值 +extern void set_output_20ma_pwm(uint16_t value); ///< 设置输出20mA时的PWM值 +extern void set_app_preload_language_flag(uint8_t language); ///< 设置预加载语言标志位 +extern void set_app_preload_bootload_flag(uint8_t flag); ///< 设置预加载BOOTLOAD标志位 +extern void set_app_preload_bootload_jump_flag(app_preload_bootload_jump_e flag); ///< 设置预加载BOOTLOAD标志位 + +/************************************** 通过电阻测算,只在测试程序中使用 **************************************/ +extern float32 actual_adc_convert_percent(uint16_t adc); ///< 实际行程ADC值转换为百分比 +extern float32 loop_current_convert(uint16_t adc); ///< 回路电流检测转换 +extern float32 ip_dac2current(uint16_t dac); ///< DAC:IP输出电流值转换 +extern float32 ip2current(void); ///< IP输出电流值转换 +extern void pwm_duty2current(float32 cur_ma); ///< PWM输出电流值转换 + +#endif // __BOARD_H__ diff --git a/User/board/inc/eeprom_fm24.h b/User/board/inc/eeprom_fm24.h new file mode 100644 index 0000000..a11409c --- /dev/null +++ b/User/board/inc/eeprom_fm24.h @@ -0,0 +1,100 @@ +/** + * @file eeprom_fm24.h + * @author xxx + * @date 2023-08-30 14:05:55 + * @brief FM24系列EEPROM驱动 https://zhuanlan.zhihu.com/p/598934638 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __EEPROM_FM24_H__ +#define __EEPROM_FM24_H__ +#include "main.h" + +//========在此设定芯片地址============= + +#define W_ADD_COM 0xa0 // 写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0 + +#define R_ADD_COM 0xa1 // 读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1 + +//=======在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512 + +//=======在此设定芯片型号, 1代表24C01; 16代表24C16; 512代表24C512 + +#define e2prom 256 // + +#if e2prom == 1 +#define FM24_PAGE_SIZE 16 +#define FM24_SIZE (128 * 8) +#elif e2prom == 2 +#define FM24_PAGE_SIZE 16 +#define FM24_SIZE (256 * 8) +#elif e2prom == 4 +#define FM24_PAGE_SIZE 32 +#define FM24_SIZE (512 * 8) +#elif e2prom == 8 +#define FM24_PAGE_SIZE 64 +#define FM24_SIZE (1024 * 8) +#elif e2prom == 16 +#define FM24_PAGE_SIZE 128 +#define FM24_SIZE (2048 * 8) +#elif e2prom == 32 +#define FM24_PAGE_SIZE 128 +#define FM24_SIZE (4096 * 8) +#elif e2prom == 64 +#define FM24_PAGE_SIZE 256 +#define FM24_SIZE (8192 * 8) +#elif e2prom == 128 +#define FM24_PAGE_SIZE 256 +#define FM24_SIZE (16384) +#elif e2prom == 256 +#define FM24_PAGE_SIZE 512 +#define FM24_SIZE (32768) // 32K +#elif e2prom == 512 +#define FM24_PAGE_SIZE 512 +#define FM24_SIZE (65536) +#endif + +/** + * @brief Initializes the FM24 EEPROM module. + */ +extern void eeprom_fm24_init(void); + +/** + * @brief Deinitializes the FM24 EEPROM module. + */ +extern void eeprom_fm24_dinit(void); + +/** + * @brief Enables the FM24 EEPROM module. + */ +extern void eeprom_fm24_enable(void); + +/** + * @brief Disables the FM24 EEPROM module. + */ +extern void eeprom_fm24_disable(void); + +/** + * @brief Reads data from the FM24 EEPROM module. + * @param read_addr The starting address to read from. + * @param data Pointer to the buffer to store the read data. + * @param length The number of bytes to read. + * @return TRUE if the read operation is successful, FALSE otherwise. + */ +extern BOOL eeprom_fm24_read(uint32_t read_addr, uint8_t *data, uint16_t length); + +/** + * @brief Writes data to the FM24 EEPROM module. + * @param write_addr The starting address to write to. + * @param data Pointer to the data to be written. + * @param length The number of bytes to write. + * @return TRUE if the write operation is successful, FALSE otherwise. + */ +extern BOOL eeprom_fm24_write(uint32_t write_addr, uint8_t *data, uint16_t length); + +/** + * @brief Performs a test on the FM24 EEPROM module. + */ +extern void eeprom_fm24_test(void); + +#endif // __EEPROM_FM24_H__ diff --git a/User/board/inc/eeprom_lc02b.h b/User/board/inc/eeprom_lc02b.h new file mode 100644 index 0000000..214ea9e --- /dev/null +++ b/User/board/inc/eeprom_lc02b.h @@ -0,0 +1,47 @@ +/** + * @file eeprom_lc02b.h + * @author xxx + * @date 2023-12-27 14:44:02 + * @brief + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __EEPROM_LC02B_H +#define __EEPROM_LC02B_H +#include "main.h" +#include "entity.h" + + + +/** + * @brief Initializes the LC02B EEPROM module. + */ +void eeprom_lc02b_init(void); + +/** + * @brief Deinitializes the LC02B EEPROM module. + */ +void eeprom_lc02b_dinit(void); + +/** + * @brief Writes data to the LC02B EEPROM module. + * + * @param write_addr The starting address to write the data. + * @param data The pointer to the data to be written. + * @param length The length of the data to be written. + */ +void eeprom_lc02b_write(uint32_t write_addr, uint8_t *data, uint16_t length); + +/** + * @brief Reads data from the LC02B EEPROM module. + * + * @param read_addr The starting address to read the data. + * @param data The pointer to store the read data. + * @param length The length of the data to be read. + */ +void eeprom_lc02b_read(uint32_t read_addr, uint8_t *data, uint16_t length); + +/** + * @brief Performs a test on the LC02B EEPROM module. + */ +void eeprom_lc02b_test(void); +#endif // !__EEPROM_LC02B_H diff --git a/User/board/inc/eeprom_m95.h b/User/board/inc/eeprom_m95.h new file mode 100644 index 0000000..0adb7c9 --- /dev/null +++ b/User/board/inc/eeprom_m95.h @@ -0,0 +1,129 @@ +/** + * @file eeprom_m95.h + * @author xxx + * @date 2023-08-30 14:05:55 + * @brief 头文件 eeprom_m95.h + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __EEPROM_M95_H +#define __EEPROM_M95_H +#include "main.h" +#include "entity.h" + +#define _M95010_ 128 +#define _M95020_ 256 +#define _M95040_ 512 + +#define _M95080_ 1024 +#define _M95160_ 2048 +#define _M95320_ 4096 +#define _M95640_ 8192 + +#define _M95128_ 16384 +#define _M95256_ 32768 + +#define _M95512_ 65536 // 65K +#define _M95M02_ 262144 // 256K + +#define _M95_SIZE _M95512_ + +#define M95_CMD_RDSR 0x05 /*!< Read Status Register instruction */ +#define M95_CMD_WRSR 0x01 /*!< Write Status Register instruction */ + +#define M95_CMD_WREN 0x06 /*!< Write enable instruction */ +#define M95_CMD_WRDI 0x04 /*!< Write disable instruction */ + +#define M95_CMD_READ 0x03 /*!< Read from Memory instruction */ +#define M95_CMD_WRITE 0x02 /*!< Write to Memory instruction */ + +// Instruction available only for the M95_2-D device. +#define M95_CMD_RDID 0x83 /*!< Read identification page*/ +#define M95_CMD_WRID 0x82 /*!< Write identification page*/ +#define M95_CMD_RDLS 0x83 /*!< Reads the Identification page lock status*/ +#define M95_CMD_LID 0x82 /*!< Locks the Identification page in read-only mode*/ + +#define M95_DUMMY_BYTE 0xA5 // 虚拟字节 + +// 定义存储器大小(Bytes) +typedef enum +{ + M95_PAGE_SIZE_16 = 16, // _M95010_ 、_M95020_ 、_M95040_ + M95_PAGE_SIZE_32 = 32, // _M95080_ 、_M95160_、_M95320_、_M95640_ + M95_PAGE_SIZE_64 = 64, // _M95128_、_M95256_ + M95_PAGE_SIZE_128 = 128, // _M95512_ + M95_PAGE_SIZE_256 = 256, // _M95M02_ +} m95_page_size_e; + +typedef enum +{ + M95_1, + M95_2, + M95_MAX, +} m95_number_e; // 板卡上2块m95芯片定义 + +typedef struct +{ + m95_number_e num; + uint32_t page_size; + uint32_t total_size; + spi_t *spi; + uint8_t address_bytes; // M95M02 地址大小3个字节,其余M95型号芯片为2个字节 + uint8_t *rxbuf; + uint8_t *txbuf; +} m95_number_t; + +extern __IO m95_number_e current_m95_number; ///< 当前使用的m95芯片编号 +extern m95_number_t eeprom_m95s[M95_MAX]; ///< m95芯片数组 + +/** + * @brief Initializes the M95 EEPROM module. + * + * @param num The M95 EEPROM number. + */ +extern void eeprom_m95_init(m95_number_e num); + +/** + * @brief Deinitializes the M95 EEPROM module. + * + * @param num The M95 EEPROM number. + */ +extern void eeprom_m95_dinit(m95_number_e num); + +/** + * @brief Enables the M95 EEPROM module. + */ +extern void eeprom_m95_enable(void); + +/** + * @brief Disables the M95 EEPROM module. + */ +extern void eeprom_m95_disable(void); + +/** + * @brief Reads data from the M95 EEPROM module. + * + * @param num The M95 EEPROM number. + * @param read_addr The address to read from. + * @param data The buffer to store the read data. + * @param length The number of bytes to read. + */ +extern void eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data, uint16_t length); + +/** + * @brief Writes data to the M95 EEPROM module. + * + * @param num The M95 EEPROM number. + * @param write_addr The address to write to. + * @param data The data to write. + * @param length The number of bytes to write. + */ +extern void eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *data, uint16_t length); + +/** + * @brief Performs a test on the M95 EEPROM module. + * + * @param num The M95 EEPROM number. + */ +extern void eeprom_m95_test(m95_number_e num); +#endif // __EEPROM_M95_H diff --git a/User/board/inc/leds.h b/User/board/inc/leds.h new file mode 100644 index 0000000..4d0ba3d --- /dev/null +++ b/User/board/inc/leds.h @@ -0,0 +1,55 @@ +#ifndef __LEDS_H__ +#define __LEDS_H__ + +#include "lib.h" +typedef enum +{ + LEDS_1_RED, + LEDS_1_GREEN, + LEDS_1_YELLOW, + LEDS_2_ORANGE, + LEDS_2_BLUE, + LEDS_MAX, +} leds_e; + +/** + * @brief Initializes the LEDs. + */ +extern void leds_init(void); + +/** + * @brief Deinitializes the LEDs. + */ +extern void leds_dinit(void); + +/** + * @brief Turns on the specified LED. + * + * @param led The LED to turn on. + */ +extern void leds_on(leds_e led); + +/** + * @brief Turns on all LEDs. + */ +extern void leds_on_all(void); + +/** + * @brief Turns off the specified LED. + * + * @param led The LED to turn off. + */ +extern void leds_off(leds_e led); + +/** + * @brief Turns off all LEDs. + */ +extern void leds_off_all(void); + +/** + * @brief Toggles the state of the specified LED. + * + * @param led The LED to toggle. + */ +extern void leds_toggle(leds_e led); +#endif // !__LEDS_H__ diff --git a/User/board/inc/ntc_3950.h b/User/board/inc/ntc_3950.h new file mode 100644 index 0000000..c22c39b --- /dev/null +++ b/User/board/inc/ntc_3950.h @@ -0,0 +1,15 @@ +/** + * @file ntc_3950.h + * @author xxx + * @date 2023-08-30 14:05:55 + * @brief 头文件 ntc_3950.h + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __NTC_B3950_H__ +#define __NTC_B3950_H__ +#include "main.h" + +extern float32_u ntc_get_temp(uint16_t adc); ///< 获取温度值 + +#endif // __NTC_B3950_H__ diff --git a/User/board/inc/rtc_rx8010.h b/User/board/inc/rtc_rx8010.h new file mode 100644 index 0000000..41675b4 --- /dev/null +++ b/User/board/inc/rtc_rx8010.h @@ -0,0 +1,93 @@ +/** + * @file rtc_rx8010.h + * @author xxx + * @date 2023-08-30 14:05:55 + * @brief 头文件 rtc_rx8010.h + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __RTC_RX8010_H__ +#define __RTC_RX8010_H__ +#include "main.h" + +#define RTC_DEVICE_ADDR 0x32 + +#define RTC_WR_ADDR ((RTC_DEVICE_ADDR << 1) | 0) +#define RTC_RD_ADDR ((RTC_DEVICE_ADDR << 1) | 1) + +#define RTC_FLAG_ADDR 0x1e +#define RTC_CLOCK_ADDR 0x10 +#define RTC_CONTROL_ADDR 0x1f + +#define RTC_REG17_ADDR 0x17 +#define RTC_REG17_DATA 0xd8 + +#define RTC_REG30_ADDR 0x30 +#define RTC_REG30_DATA 0x00 + +#define RTC_REG31_ADDR 0x31 +#define RTC_REG31_DATA 0x08 + +#define RTC_IRQ_ADDR 0x32 +#define RTC_IRQ_DATA 0x00 + +typedef enum +{ + SUN = BIT0, + MON = BIT1, + TUE = BIT2, + WED = BIT3, + THUR = BIT4, + FRI = BIT5, + SAT = BIT6 +} rtc_week_e; // 星期码 + +typedef struct +{ + uint8_t year; // 7 bit - 1 63 + uint8_t month; // 4 bit + uint8_t day; // 5 bit + uint8_t weekday; // rtc_week_e + uint8_t hour; // 5 bit + uint8_t minute; // 6 bit + uint8_t second; // 6 bit +} rtc_date; + +/** + * @brief Initializes the RTC module. + * @return TRUE if the initialization is successful, FALSE otherwise. + */ +extern BOOL rtc_init(void); + +/** + * @brief Deinitializes the RTC module. + * @return TRUE if the deinitialization is successful, FALSE otherwise. + */ +extern BOOL rtc_dinit(void); + +/** + * @brief Retrieves the current clock time from the RTC module. + * @param read_buf Pointer to the buffer to store the clock time. + * @return TRUE if the clock time is successfully retrieved, FALSE otherwise. + */ +extern BOOL rtc_get_clock_time(uint8_t *read_buf); + +/** + * @brief Sets the clock time in the RTC module. + * @param data Pointer to the RTC date structure containing the new clock time. + * @return TRUE if the clock time is successfully set, FALSE otherwise. + */ +extern BOOL rtc_set_clock_time(rtc_date *data); + +/** + * @brief Converts the weekday value to a human-readable format. + * @param weekday Pointer to the weekday value to be converted. + */ +extern void rtc_weekday_convert(uint8_t *weekday); + +/** + * @brief Converts the weekday value from a human-readable format to the RTC format. + * @param weekday Pointer to the weekday value to be converted. + */ +extern void rtc_weekday_rconvert(uint8_t *weekday); +#endif // !__RTC_RX8010_H__ diff --git a/User/board/src/board.c b/User/board/src/board.c new file mode 100644 index 0000000..3fa092f --- /dev/null +++ b/User/board/src/board.c @@ -0,0 +1,1061 @@ +/** + * @file board.c + * @author xxx + * @date 2023-09-12 13:52:37 + * @brief + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#include "board.h" +#include "entity.h" +#include "delay.h" + +#include "filter.h" +void SystemClock_Config(void); + +static BOOL driver_init_flag = FALSE; + +static uint16_t board_cache[BOARD_CACHE_MAX]; ///< 调节缓存 +static lpf_t lpf_temperature; ///< 温度滤波器 +__IO static BOOL system_clock_config_flag = FALSE; ///< 系统时钟配置改变标志 + +__IO uint8_t app_preload_flag __attribute__((at(APP_PRELOAD_AREA))); // 预加载标志 +__IO uint8_t app_preload_language_flag __attribute__((at(APP_PRELOAD_AREA + 1))); // 语言标志 +__IO uint8_t app_preload_bootload_flag __attribute__((at(APP_PRELOAD_AREA + 2))); // 触发BOOTLOAD启动标志(在用户代码中接受代码文件) +__IO uint8_t app_preload_bootload_jump_flag __attribute__((at(APP_PRELOAD_AREA + 3))); // 触发BOOTLOAD跳转更新标志(在BOOTLOAD代码中更新用户代码) +__IO uint32_t app_preload_cupid_encrypt __attribute__((at(APP_PRELOAD_AREA + 4))); // 加密后的CPUID +/***************************************** 板卡初始化相关函数 *****************************************/ + +/** + * @brief LCD设计 + * @return {*} + * @note + */ +void lcd_design(void) +{ +} + +/** + * @brief LCD初始化 + * @return {*} + * @note + */ +void lcd_init(void) +{ + // 设置功能引脚 + GPIO_SET_OUTPUT(LCD_PWR_GPIO_Port, LCD_PWR_Pin); + GPIO_SET_OUTPUT(LCD_CS_GPIO_Port, LCD_CS_Pin); + GPIO_SET_OUTPUT(LCD_DISP_GPIO_Port, LCD_DISP_Pin); + + if (0 == LCD_IS_POWER_ON()) + { + } +} + +/** + * @brief LCD反初始化 + * @return {*} + * @note + */ +void lcd_dinit(void) +{ +} + +/** + * @brief 功耗引脚初始化 + * @return {*} + * @note + */ +void driver_init(void) +{ + // 标志位检查:driver_init_flag = TRUE,表示已经初始化 + if (driver_init_flag == TRUE) + { + return; + } + driver_init_flag = TRUE; + + pdctrl_run(); // 控制输出使能 + PWM_START(TIM3, LL_TIM_CHANNEL_CH3); // PWM OUT使能 +} + +/** + * @brief 功耗引脚反初始化 + * @return {*} + * @note + */ +void driver_dinit(void) +{ + // 标志位检查:driver_init_flag = FALSE,表示已经反初始化 + if (driver_init_flag == FALSE) + { + return; + } + driver_init_flag = FALSE; + + pdctrl_stop(); // 控制输出禁用 + PWM_STOP(TIM3, LL_TIM_CHANNEL_CH3); // PWM OUT禁用 +} + +/** + * @brief 板卡初始化 + * @return {*} + * @note + */ +void board_init(void) +{ + VIP_H_EN_DISABLE(); // IP禁用,满足条件时才使能 + + adc_init(ADCS_1, ADC1, DMA1, LL_DMA_CHANNEL_1, 30, + IN5 | IN6 | IN7 | IN8 | IN9 | IN11 | IN12 | IN13 | IN14 | INTEMP | INVREF); // 初始化ADC1通道,默认采集AD + + adc_init(ADCS_2, ADC2, DMA1, LL_DMA_CHANNEL_2, 10, + IN5 | IN6); // 初始化ADC2通道,慢速采集通道 + + rtc_init(); // 初始化RTC + eeprom_m95_init(M95_1); // 初始化SPI EEPROM1 + eeprom_m95_init(M95_2); // 初始化SPI EEPROM2 + eeprom_fm24_init(); // 初始化 IIC EEPROM + eeprom_lc02b_init(); // 初始化 IIC EEPROM + leds_init(); // 初始化LED + + lpf_init(&lpf_temperature); + system_clock_config_low(); + // debug_freeze_watchdog(); // 冻结看门狗 +} + +void board_dinit(void) +{ + adc_dinit(ADCS_1); // ADC反初始化 + DISABLE_TIM(TIM6); + DISABLE_TIM(TIM7); + driver_dinit(); + + rtc_dinit(); // RTC反初始化 + eeprom_m95_dinit(M95_1); + eeprom_m95_dinit(M95_2); + eeprom_fm24_dinit(); + eeprom_lc02b_dinit(); + leds_dinit(); // LED Deinitialization + lcd_dinit(); // LCD screen Deinitialization +} + +/** + * @brief 板卡工作暂停 + * @return {*} + * @note 在用户层处理bootload接收数据时需要暂时关闭一些应用层的处理 + */ +void board_work_stop_or_run(void) +{ + static BOOL stop_or_run_state = FALSE; + + if (get_app_preload_bootload_flag() != stop_or_run_state) + { + // 如果stop_or_run_state是FALSE,那么app_preload_bootload_flag是TRUE,表示当前需要暂停工作 + // 目前先暂停TIM7控制模块,TIM6的任务执行不受影响,因为任务模块会执行最简单的任务 + if (stop_or_run_state == FALSE) + { + DISABLE_TIM(TIM7); + } + else + { + ENABLE_TIM(TIM7); + } + stop_or_run_state = get_app_preload_bootload_flag(); + } +} + +/** + * @brief 缓存数据初始化 + * @return {*} + * @note + */ +void board_cache_reset(void) +{ + for (uint8_t i = 0; i < BOARD_CACHE_MAX; i++) + { + board_cache[i] = 0; + } +} + +/** + * @brief 缓存数据获取 + * @param {board_cache_e} index + * @return {*} + * @note + */ +uint16_t board_cache_get(board_cache_e index) +{ + return board_cache[index]; +} + +/** + * @brief 系统时钟配置低频 + * @return {*} + * @note 2M 默认使用系统时钟配置低频 + */ +// static void system_clock_config_low_2m(void) +//{ +// LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); +// while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) +// { +// } +// LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); +// while (LL_PWR_IsActiveFlag_VOS() != 0) +// { +// } +// LL_RCC_HSE_Enable(); + +// /* Wait till HSE is ready */ +// while (LL_RCC_HSE_IsReady() != 1) +// { +// } +// LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2); +// LL_RCC_PLL_EnableDomain_SYS(); +// LL_RCC_PLL_Enable(); + +// /* Wait till PLL is ready */ +// while (LL_RCC_PLL_IsReady() != 1) +// { +// } +// LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + +// /* Wait till System clock is ready */ +// while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) +// { +// } +// LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_16); +// LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); +// LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + +// LL_Init1msTick(2000000); + +// LL_SetSystemCoreClock(2000000); +//} + +void system_clock_config_set_flag(BOOL flag) +{ + system_clock_config_flag = flag; +} + +/** + * @brief 系统时钟配置低频 + * @return {*} + * @note 4M 默认使用系统时钟配置低频 + */ +void system_clock_config_low(void) +{ + if (system_clock_config_flag == FALSE) + { + return; + } + system_clock_config_set_flag(FALSE); + + // if (udevice.dev_algorithm_mode == MODE_VARIABLE_FREQUENCY_CONTROL_ALGORITHM) + // { + // system_clock_config_low_2m(); + // } + // else + // { + // SystemClock_Config(); + // } + SystemClock_Config(); + + uint32_t hclk = SystemCoreClock / 1000000; + delay_init(hclk); + uint16_t pres = (hclk * 100) - 1; + if (LL_TIM_GetPrescaler(TIM6) != pres) + { + LL_TIM_SetPrescaler(TIM6, pres); + } + if (LL_TIM_GetPrescaler(TIM7) != pres) + { + LL_TIM_SetPrescaler(TIM7, pres); + } + uint32_t reload = (hclk * 1000) - 1; + pdctrl_pwm_set_arr(reload); + if (LL_TIM_GetAutoReload(TIM3) != reload) + { + LL_TIM_SetAutoReload(TIM3, reload); + } +} + +/** + * @brief 系统时钟配置高频 + * @return {*} + * @note 16M + */ +void system_clock_config_hight(void) +{ + if (system_clock_config_flag == FALSE) + { + return; + } + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_0); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_0) + { + } + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + while (LL_PWR_IsActiveFlag_VOS() != 0) + { + } + LL_RCC_HSE_Enable(); + + /* Wait till HSE is ready */ + while (LL_RCC_HSE_IsReady() != 1) + { + } + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_1, 8, LL_RCC_PLLR_DIV_2); + LL_RCC_PLL_EnableDomain_SYS(); + LL_RCC_PLL_Enable(); + + /* Wait till PLL is ready */ + while (LL_RCC_PLL_IsReady() != 1) + { + } + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + + /* Wait till System clock is ready */ + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + } + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + LL_Init1msTick(16000000); + + LL_SetSystemCoreClock(16000000); + + uint32_t hclk = SystemCoreClock / 1000000; + uint16_t pres = (hclk * 100) - 1; + if (LL_TIM_GetPrescaler(TIM6) != pres) + { + LL_TIM_SetPrescaler(TIM6, pres); + } + if (LL_TIM_GetPrescaler(TIM7) != pres) + { + LL_TIM_SetPrescaler(TIM7, pres); + } + uint32_t reload = (hclk * 1000) - 1; + pdctrl_pwm_set_arr(reload); + if (LL_TIM_GetAutoReload(TIM3) != reload) + { + LL_TIM_SetAutoReload(TIM3, reload); + } +} + +/***************************************** 板卡LCD操作相关函数 *****************************************/ + +/** + * @brief LCD刷新 + * @return {*} + * @note + */ +void gui_flush(void) +{ + +} + +/** + * @brief LCD刷新并清除缓存 + * @return {*} + * @note + */ +void gui_flush_Clear(void) +{ + +} + +/** + * @brief LCD全屏清除 + * @return {*} + * @note + */ +void gui_clr(void) +{ + +} + +/** + * @brief LCD设置清屏标志 + * @return {*} + * @note + */ +void gui_set_clear_flag(void) +{ + +} + +/** + * @brief LCD获取清屏标志 + * @return {*} + * @note + */ +BOOL gui_get_clear_flag(void) +{ + return TRUE; +} + +/** + * @brief LCD全屏填充 + * @return {*} + * @note + */ +void gui_full(void) +{ + +} + +/** + * @brief LCD启动 + * @return {*} + * @note + */ +void gui_open() +{ + +} + +/** + * @brief LCD关闭 + * @return {*} + * @note + */ +void gui_close() +{ + +} + +/** + * @brief 设置扫描方向 + * @return {*} + * @note + */ +void gui_set_scandir(uint8_t dir) +{ + +} + +/***************************************** 板卡参数相关函数 *****************************************/ +/** + * @brief 根据目标行程计算DAC输出理论值 + * @param {float32} output - 目标行程(百分比) + * @return {uint16_t} DAC输出理论值 + * @note 计算公式如下: + * > (Osh-Osl)/(Ish-Isl)=(Ov-Osl)/(Iv-Isl)

+ * > Ov=[(Osh-Osl)*(Iv-Isl)/(Ish-Isl)]+Osl

+ */ +uint16_t get_dac(float32 output) +{ + return ((udevice.output_max - udevice.output_min) * (output - 0) / (100 - 0)) + udevice.output_min; +} + +/** + * @brief PWM输出阀位百分比 + * @param {float32} position_per-阀位百分比 + * @return {*} + * @note 阀位反馈输出, 0%输出4.00mA, 100.0%输出20.00mA + *> 0% - 4.0mA

+ *> 10% - 5.6mA

+ *> 20% - 7.2mA

+ *> 30% - 8.8mA

+ *> 40% - 10.4mA

+ *> 50% - 12.0mA

+ *> 55% - 12.8mA

+ *> 60% - 13.6mA

+ *> 70% - 15.2mA

+ *> 80% - 16.8mA

+ *> 90% - 18.4mA

+ *> 100% - 20.0mA

+ */ +void pwm_output_position(float32 position_per) +{ + float32 ftemp = 0; + + // 根据阀位百分比计算对应的电流 + ftemp = position_per; + ftemp *= 16; + ftemp += 400; + + // 根据校准参数计算占空比 + ftemp *= calib_param[CALIBPARA_VIP].value[0]; + ftemp += calib_param[CALIBPARA_VIP].value[1]; + + // PWM输出 + PWM_SET_DUTY(TIM2, 4, ftemp); +} + +/** + * @brief 校准4-20mA输出电流 + * @return {*} + * @note + */ +void calib_loop(void) +{ +#define MA4 (LOOP_CURRENT_MIN * 1000) +#define MA20 (LOOP_CURRENT_MAX * 1000) + uint16_t ma = 0, adc = 0; + float32 f; + // 计算校准参数 + ma = MA20 - MA4; + adc = board_cache[BOARD_CACHE_2] - board_cache[BOARD_CACHE_1]; + f = ma; + f = f / adc; + calib_param[CALIBPARA_LOOP].value[0] = f / 10; + f = f * board_cache[BOARD_CACHE_2]; + calib_param[CALIBPARA_LOOP].value[1] = (MA20 - f) / 10; + + calib_param[CALIBPARA_LOOP].is_calibration = TRUE; +} + +/** + * @brief 校准压力表 + * @return {*} + * @note + */ +void calib_kpa(void) +{ +#define PRESSURE_200_KPA 200.0f // 200kPa +#define PRESSURE_400_KPA 400.0f // 400kPa + uint16_t ma = 0, adc = 0; + float32 f; + // 计算校准参数 + ma = PRESSURE_400_KPA - PRESSURE_200_KPA; + adc = board_cache[BOARD_CACHE_2] - board_cache[BOARD_CACHE_1]; + f = ma; + f = f / adc; + calib_param[CALIBPARA_PS].value[0] = f; + f = f * board_cache[BOARD_CACHE_2]; + calib_param[CALIBPARA_PS].value[1] = PRESSURE_400_KPA - f; + + calib_param[CALIBPARA_PSB].value[0] = calib_param[CALIBPARA_PS].value[0]; + calib_param[CALIBPARA_PSB].value[1] = calib_param[CALIBPARA_PS].value[1]; + + calib_param[CALIBPARA_PB].value[0] = calib_param[CALIBPARA_PS].value[0]; + calib_param[CALIBPARA_PB].value[1] = calib_param[CALIBPARA_PS].value[1]; +} + +/** + * @brief 校准4-20mA输出电流 + * @return {*} + * @note + */ +void calib_pwm_out(void) +{ + // 计算校准参数 + float32 mA4 = 400; + float32 mA20 = 2000; + float32 TDuty4 = board_cache[BOARD_CACHE_1]; + float32 TDuty20 = board_cache[BOARD_CACHE_2]; + calib_param[CALIBPARA_VIP].value[0] = (TDuty20 - TDuty4) / (mA20 - mA4); + calib_param[CALIBPARA_VIP].value[1] = TDuty20 - calib_param[CALIBPARA_VIP].value[0] * mA20; +} +/** + * @brief 校准阀门位置参数,电压转换成%(放大10倍,1位小数) + * @return {*} + * @note 计算公式如下: + * > k = (y2-y1) / (x2-x1)

+ * > m = y2 - k * x2

+ */ +void calib_parapos_perent(void) +{ + float32 ftmp = 0.0; + + // 直行程位置反馈 + ftmp = udevice.pos100_travel_vol - udevice.pos0_travel_vol; + calib_param[CALIBPARA_PSB].value[0] = 100 / ftmp; + + ftmp = calib_param[CALIBPARA_PSB].value[0] * udevice.pos100_travel_vol; + calib_param[CALIBPARA_PSB].value[1] = 100 - ftmp; + calib_param[CALIBPARA_PSB].is_calibration = TRUE; + + // 小回路 + ftmp = udevice.pos100_minor_vol - udevice.pos0_minor_vol; + calib_param[CALIBPARA_IPSB].value[0] = 100 / ftmp; + + ftmp = calib_param[CALIBPARA_IPSB].value[0] * udevice.pos100_minor_vol; + calib_param[CALIBPARA_IPSB].value[1] = 100 - ftmp; + + calib_param[CALIBPARA_IPSB].is_calibration = TRUE; +} + +/** + * @brief 获取当前实际行程ADC值 + * @return {*} + * @note + */ +uint16_t get_actual_travel_adc(void) +{ + adc_raw[ADC_PSB_CHANNEL] = adc_result_median(ADCS_1, ADC_PSB_CHANNEL); + return adc_raw[ADC_PSB_CHANNEL]; +} + +/** + * @brief 获取当前实际行程ADC值 + * @return {*} + * @note + */ +uint16_t get_actual_travel_adc_average(void) +{ + adc_raw[ADC_PSB_CHANNEL] = adc_result_average(ADCS_1, ADC_PSB_CHANNEL); + return adc_raw[ADC_PSB_CHANNEL]; +} + +/** + * @brief 获取当前实际行程百分比 + * @param {uint16_t} adc + * @return {*} + * @note + */ +float32 actual_adc_convert_percent(uint16_t adc) +{ + float32 f = adc * 1.0f; + // 计算当前位置 + f *= calib_param[CALIBPARA_PSB].value[0]; + f += calib_param[CALIBPARA_PSB].value[1]; + if (f < 0) + { + f = 0; + } + if (f > 100) + { + f = 100; + } + + return f; +} + +/** + * @brief 获取当前实际行程 + * @param {uint8_t} filter 1:平均 2:中值 + * @return {*} + * @note + */ +float32 get_actual_travel(filter_e filter) +{ + uint16_t raw = 0; + + // 读取位置反馈ADC值 + if (filter == FILTER_AVERAGE) + { + raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL); + } + else if (filter == FILTER_MEDIAN) + { + raw = adc_result_median(ADCS_1, ADC_PSB_CHANNEL); + } + else + { + raw = adc_result_average(ADCS_1, ADC_PSB_CHANNEL); + } + + adc_raw[ADC_PSB_CHANNEL] = raw; + return actual_adc_convert_percent(raw); +} + +/** + * @brief 获取当前实际行程 + * @param {uint8_t} filter 1:平均 2:中值 + * @return {*} + * @note + */ +float32 get_actual_travel_2(filter_e filter) +{ + uint16_t raw = 0; + + // 读取位置反馈ADC值 + if (filter == FILTER_AVERAGE) + { + raw = adc_result_average(ADCS_2, ADC_PSB_CHANNEL); + } + else if (filter == FILTER_MEDIAN) + { + raw = adc_result_median(ADCS_2, ADC_PSB_CHANNEL); + } + else + { + raw = adc_result_average(ADCS_2, ADC_PSB_CHANNEL); + } + + adc_raw[ADC_PSB_CHANNEL] = raw; + return actual_adc_convert_percent(raw); +} + +/** + * @brief 获取当前回路电流 + * @return {float32} 回路电流值 + * @note + */ +float32 get_current(void) +{ + float32 f = 0.0; + + // 读取回路电流ADC值 + adc_raw[ADC_LOOP_CHANNEL] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); + f = adc_raw[ADC_LOOP_CHANNEL]; + + // 计算回路电流 + f *= calib_param[CALIBPARA_LOOP].value[0]; + f += calib_param[CALIBPARA_LOOP].value[1]; + f = f / 100; + + if (f < 0) + { + f = 0; + } + + return f; +} + +/** + * @brief 获取当前回路电流,保留小数点后1位 + * @param {float32} current + * @return {*} + * @note + */ +float32 get_current_deal(float32 current) +{ + // 判断current小数点后第二位是否大于5 + if ((uint16_t)(current * 100) % 10 >= 5) + { + return (uint16_t)(current * 10) * 0.1f + 0.1f; + } + else + { + return (uint16_t)(current * 10) * 0.1f; + } +} + +/** + * @brief 获取当前温度值 + * @return {float32} 温度值 + * @note + */ +float32 get_temperature(void) +{ + float32 tmp = 0.0f; + // 采集ADC原始数据 + adc_raw[ADC_NTC_CHANNEL] = adc_result_average(ADCS_1, ADC_NTC_CHANNEL); + + // 使用NTC算法计算温度值 + tmp = ntc_get_temp(adc_raw[ADC_NTC_CHANNEL]).f; + tmp = lpf_update(&lpf_temperature, tmp); + return tmp; +} + +/** + * @brief 获取当前流量 + * @return {*} + * @note + */ +float32 get_flow(void) +{ + float32 v = 0.0f; + adc_raw[ADC_FLOW] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL); + v = ((CPU_VREF * adc_raw[ADC_FLOW] / ADC_MAX) - 0.4) * 600 / 1.6; + + return v < 0 ? 0 : v; +} + +/** + * @brief 获取当前压力 + * @return {float32} 压力值 + * @note + */ +float32 get_pressure(pressure_index_e id) +{ + float32 f = 0.0; + + switch (id) + { + case ADC_INDEX_PRESSSOURCE: + // 读取气源压力ADC + adc_raw[ADC_BP_CHANNEL] = adc_result_average(ADCS_1, ADC_BP_CHANNEL); + f = adc_raw[ADC_BP_CHANNEL]; + // 计算气源压力 + f *= calib_param[CALIBPARA_PS].value[0]; + f += calib_param[CALIBPARA_PS].value[1]; + rt_data.pressure_s = f; + break; + case ADC_INDEX_PRESSOUTA: + // 读取A路压力ADC + adc_raw[ADC_BPA_CHANNEL] = adc_result_average(ADCS_1, ADC_BPA_CHANNEL); + f = adc_raw[ADC_BPA_CHANNEL]; + // 计算A路压力 + f *= calib_param[CALIBPARA_PSB].value[0]; + f += calib_param[CALIBPARA_PSB].value[1]; + rt_data.pressure_a = f; + break; + case ADC_INDEX_PRESSOUTB: + // 读取B路压力ADC + adc_raw[ADC_BPB_CHANNEL] = adc_result_average(ADCS_1, ADC_BPB_CHANNEL); + f = adc_raw[ADC_BPB_CHANNEL]; + // 计算B路压力 + f *= calib_param[CALIBPARA_PB].value[0]; + f += calib_param[CALIBPARA_PB].value[1]; + rt_data.pressure_b = f; + break; + default: + break; + } + return f; +} + +/***************************** 通过电阻测算,只在测试程序中使用 *****************************/ +/** + * @brief 回路电流检测转换 + * @param {uint16_t} adc + * @return {float32} 回路电流值 + * @note 计算公式如下: + * > 压力和电流关系:(adc/4096)*VREF_VALUE/(5*20) = ma

+ * > 简化后:adc*VREF_VALUE/409600 = ma

+ */ +float32 loop_current_convert(uint16_t adc) +{ + float32 f; + f = ((float32)(adc * VREF_VALUE)) / 409600; + return f; +} + +/** + * @brief DAC:IP输出电流值转换 + * @param {uint16_t} dac + * @return {float32} IP输出电流值 + * @note + */ +float32 ip_dac2current(uint16_t dac) +{ + float32 vol = 0, cur = 0; + // 计算电压值 mv + vol = (float32)dac / 4096 * VREF_VALUE; + + // 计算电流值 ma + cur = vol / (40 * 40); + + // 如果电流值大于2.5,则设置为2.5 + if (cur > 2.5f) + { + cur = 2.5; + } + + return cur; +} + +/** + * @brief IP输出电流值转换 + * @return {*} + * @note + */ +float32 ip2current(void) +{ + float32 cur = 0; + adc_raw[ADC_VIP_CHANNEL] = adc_result_average(ADCS_1, ADC_VIP_CHANNEL); + // 计算电流值 ma + cur = (float32)adc_raw[ADC_VIP_CHANNEL] / (float32)(10 * 101); + return cur; +} + +/** + * @brief PWM输出电流值转换 + * @param {float32} current + * @return {*} + * @note: 计算公式如下: + * > I_OUT=3V*Duty/10K*100(mA) + */ +void pwm_duty2current(float32 cur_ma) +{ + float32 current; + + if (cur_ma < 4) + current = 4; + else if (cur_ma > 20) + current = 20; + else + current = cur_ma; + + float32 duty = current / 30; + uint16_t count = duty * 4095; + PWM_CTRL_OUTPUT(count); +} + +/** + * @brief 获取RTC时间 + * @param {uDateTime_TypeDef} *time + * @return {*} + * @note + */ +void get_timestamp(uDateTime_TypeDef *time) +{ + uint8_t tmp[7]; + rtc_get_clock_time(tmp); + + time->Date.Year = tmp[6]; // 将年存储在data结构体的year字段中 + time->Date.Month = tmp[5]; // 将月存储在data结构体的month字段中 + time->Date.Day = tmp[4]; // 将日存储在data结构体的day字段中 + time->Date.Hour = tmp[2]; // 将时存储在data结构体的hour字段中 + time->Date.Minute = tmp[1]; // 将分存储在data结构体的minute字段中 + time->Date.Second = tmp[0]; // 将秒存储在data结构体的second字段中 +} + +void get_real_time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *min, uint8_t *sec) +{ + get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time); + *year = hex_format_dec(rt_data.save.real_time.Date.Year); + *month = hex_format_dec(rt_data.save.real_time.Date.Month); + *day = hex_format_dec(rt_data.save.real_time.Date.Day); + *hour = hex_format_dec(rt_data.save.real_time.Date.Hour); + *min = hex_format_dec(rt_data.save.real_time.Date.Minute); + *sec = hex_format_dec(rt_data.save.real_time.Date.Second); +} + +void set_real_time(uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) +{ + rtc_date date = { + .year = year, + .month = month, + .day = day, + .hour = hour, + .minute = min, + .second = sec, + .weekday = get_weekday(2000 + hex_format_dec(year), + hex_format_dec(month), + hex_format_dec(day)), + }; + rtc_weekday_convert(&date.weekday); + rtc_set_clock_time(&date); + get_timestamp((uDateTime_TypeDef *)&rt_data.save.real_time); +} + +/** + * @brief 设置输出PWM校准电流 + * @return {*} + * @note 计算公式如下: + * > y = k*x + m (x表示电流,y表示PWM占空比)

+ * > k = (TDuty20 - TDuty4) / (mA20 - mA4)

+ * > m = TDuty20 - k * mA20

+ */ + +void set_pwm_calib_current() +{ + float32 mA4 = 400; + float32 mA20 = 2000; + float32 TDuty4 = udevice.output_4ma_duty; + float32 TDuty20 = udevice.output_20ma_duty; + calib_param[CALIBPARA_VIP].value[0] = (TDuty20 - TDuty4) / (mA20 - mA4); + calib_param[CALIBPARA_VIP].value[1] = TDuty20 - calib_param[CALIBPARA_VIP].value[0] * mA20; +} + +/** + * @brief 读取4mA输入时的ADC电压 + * @return {*} + */ +void set_loop_4ma(void) +{ + board_cache[BOARD_CACHE_1] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); // 获取4mA输入时adc值 +} + +/** + * @brief 读取20mA输入时的ADC值 + * @return {*} + */ +void set_loop_20ma(void) +{ + board_cache[BOARD_CACHE_2] = adc_result_average(ADCS_1, ADC_LOOP_CHANNEL); +} + +/** + * @brief 读取200kPa输入时的ADC电压 + * @return {*} + */ +void set_200kpa(void) +{ + board_cache[BOARD_CACHE_1] = adc_result_average(ADCS_1, ADC_BP_CHANNEL); // 获取200kPa时adc值 +} + +/** + * @brief 读取400kPa输入时的ADC电压 + * @return {*} + */ +void set_400kpa(void) +{ + board_cache[BOARD_CACHE_2] = adc_result_average(ADCS_1, ADC_BP_CHANNEL); +} + +/** + * @brief 记录输出4mA时的PWM值 + * @return {*} + */ +void set_output_4ma_pwm(uint16_t value) +{ + board_cache[BOARD_CACHE_1] = value; +} + +/** + * @brief 记录输出20mA时的PWM值 + * @return {*} + */ +void set_output_20ma_pwm(uint16_t value) +{ + board_cache[BOARD_CACHE_2] = value; +} + +/** + * @brief 设置语言预加载标志 + * @param {uint8_t} language + * @return {*} + * @note + */ +void set_app_preload_language_flag(uint8_t flag) +{ + if (app_preload_language_flag != flag) + { + app_preload_language_flag = flag; + } +} + +/** + * @brief 设置预加载BOOTLOAD标志位 + * @param {uint8_t} flag + * @return {*} + * @note + */ +void set_app_preload_bootload_flag(uint8_t flag) +{ + if (app_preload_bootload_flag != flag) + { + app_preload_bootload_flag = flag; + } +} + +/** + * @brief Get the application preload bootload flag + * @return The application preload bootload flag + */ +BOOL get_app_preload_bootload_flag(void) +{ + return app_preload_bootload_flag; +} + +/** + * @brief 设置预加载BOOTLOAD标志位 + * @param {app_preload_bootload_jump_e} flag + * @return {*} + * @note + */ +void set_app_preload_bootload_jump_flag(app_preload_bootload_jump_e flag) +{ + if (app_preload_bootload_jump_flag != flag) + { + app_preload_bootload_jump_flag = flag; + } +} + +/** + * @brief Get the application preload bootload jump flag + * @return The application preload bootload jump flag + */ +app_preload_bootload_jump_e get_app_preload_bootload_jump_flag(void) +{ + return (app_preload_bootload_jump_e)app_preload_bootload_jump_flag; +} diff --git a/User/board/src/eeprom_fm24.c b/User/board/src/eeprom_fm24.c new file mode 100644 index 0000000..2c1d1b7 --- /dev/null +++ b/User/board/src/eeprom_fm24.c @@ -0,0 +1,178 @@ +/** + * @file eeprom_fm24.c + * @author xxx + * @date 2023-08-29 07:58:27 + * @brief 用于实现FM24 EEPROM相关的读写操作 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#include "entity.h" +#include "board.h" +#include "eeprom_m95.h" +#include "eeprom_fm24.h" +#include "i2cs.h" +#include "delay.h" +#include "diagnosis.h" + +#define FM24_I2C I2C1 +#define FM24_DMA DMA1 +#define FM24_DMA_RX_CHANNEL LL_DMA_CHANNEL_7 +#define FM24_DMA_TX_CHANNEL LL_DMA_CHANNEL_6 + +#define EEPROM_FM24_SDA_PORT I2C1_SDA_GPIO_Port +#define EEPROM_FM24_SDA_PIN I2C1_SDA_Pin +#define EEPROM_FM24_SCL_PORT I2C1_SCL_GPIO_Port +#define EEPROM_FM24_SCL_PIN I2C1_SCL_Pin + +#if e2prom == 256 +#define FM24_USER_SPACE 32000 +#define FM24_ERASE_UPPER 10000000 +#endif + +i2c_t *eeprom_fm24_i2c; + +// dma发送回调函数 +static void eeprom_fm24_dma_tx_cb(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + DMA_ClEAR_FLAG(handle->dma, 6, handle->tx_dma_ok); +} + +// dma接收回调函数 +static void eeprom_fm24_dma_rx_cb(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + DMA_ClEAR_FLAG(handle->dma, 7, handle->rx_dma_ok); +} + +/** + * @brief 初始化FM24 EEPROM + * @return {*} void + * @note 初始化FM24模块时,需要配置I2C总线的相关参数 + */ +void eeprom_fm24_init(void) +{ + eeprom_fm24_i2c = i2c_create_dma(FM24_I2C, FM24_DMA, FM24_PAGE_SIZE + 2, FM24_DMA_RX_CHANNEL, eeprom_fm24_dma_rx_cb, + FM24_PAGE_SIZE + 2, FM24_DMA_TX_CHANNEL, eeprom_fm24_dma_tx_cb); + i2c_dma_set_address(eeprom_fm24_i2c, W_ADD_COM, R_ADD_COM); + // eeprom_fm24_test(); +} + +/** + * @brief FM24 EEPROM反初始化 + * @return {*} void + * @note + */ +void eeprom_fm24_dinit(void) +{ + LL_I2C_Disable(FM24_I2C); + GPIO_SET_ANALOG(EEPROM_FM24_SDA_PORT, EEPROM_FM24_SDA_PIN); + GPIO_SET_ANALOG(EEPROM_FM24_SCL_PORT, EEPROM_FM24_SCL_PIN); +} + +/** + * @brief FM24 EEPROM使能 + * @return {*} + * @note + */ +void eeprom_fm24_enable(void) +{ + // LL_I2C_Enable(FM24_I2C); +} + +/** + * @brief FM24 EEPROM失能 + * @return {*} + * @note + */ +void eeprom_fm24_disable(void) +{ + // LL_I2C_Disable(FM24_I2C); +} + +/** + * @brief FM24 EEPROM写入多个字节数据 + * @param {uint32_t} write_addr - 要写入的地址 + * @param {uint8_t} *data - 存储要写入数据的缓冲区 + * @param {uint16_t} length - 要写入的字节数 + * @return {*} + * @note + */ +BOOL eeprom_fm24_write(uint32_t write_addr, uint8_t *data, uint16_t length) +{ + BOOL res = TRUE; + uint8_t start_page = write_addr / FM24_PAGE_SIZE; // 起始页 + uint16_t start_write_size = (start_page + 1) * FM24_PAGE_SIZE - write_addr; // 第一页需要写入的字节数 + if (start_write_size > length) // 如果第一页可以写入的字节数大于总字节数 + { + res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, length); + } + else + { + res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, start_write_size); + if (res == TRUE) + { + data += start_write_size; + uint16_t end_write_size = length - start_write_size; // 剩余需要写入的字节数 + if (end_write_size > 0) + { + uint8_t page = end_write_size / FM24_PAGE_SIZE; + uint8_t remainder = end_write_size % FM24_PAGE_SIZE; + write_addr += start_write_size; + uint8_t i = 0; + for (i = 0; i < page; i++) + { + res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, FM24_PAGE_SIZE); + if (res == FALSE) + { + break; + } + + write_addr += FM24_PAGE_SIZE; + data += FM24_PAGE_SIZE; + } + if (remainder != 0 && res == TRUE) + { + res = eeprom_fm24_i2c->interface.write_mem_dma(eeprom_fm24_i2c, write_addr, 2, data, remainder); + } + } + } + } + return res; +} + +/** + * @brief FM24 EEPROM读取多个字节数据 + * @param {uint32_t} read_addr - 要读取的地址 + * @param {uint8_t} *data - 存储读取数据的缓冲区 + * @param {uint16_t} length - 要读取的字节数 + * @return {*} + * @note + */ +BOOL eeprom_fm24_read(uint32_t read_addr, uint8_t *data, uint16_t length) +{ + BOOL res = eeprom_fm24_i2c->interface.read_mem_dma(eeprom_fm24_i2c, read_addr, 2, data, length); + return res; +} + +/** + * @brief 用于FM24 EEPROM测试 + * @return {*} + * @note + */ +void eeprom_fm24_test(void) +{ +#define TEST_SIZE 30 + uint16_t test_address = FM24_SIZE - TEST_SIZE; + uint8_t buf[TEST_SIZE]; + osel_memset(buf, 0, ARRAY_LEN(buf)); + buf[0] = 0xD5; + buf[1] = 0xC8; + buf[2] = 0x00; + buf[3] = 0x01; + buf[4] = 0x02; + buf[TEST_SIZE - 1] = 0xfe; + eeprom_fm24_write(test_address, buf, TEST_SIZE); + osel_memset(buf, 0, ARRAY_LEN(buf)); + eeprom_fm24_read(test_address, buf, TEST_SIZE); + __NOP(); +} diff --git a/User/board/src/eeprom_lc02b.c b/User/board/src/eeprom_lc02b.c new file mode 100644 index 0000000..d5fa636 --- /dev/null +++ b/User/board/src/eeprom_lc02b.c @@ -0,0 +1,139 @@ +#include "eeprom_lc02b.h" +#include "delay.h" + +#define W_ADD_COM 0xa8 // 写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0 +#define R_ADD_COM 0xa9 // 读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1 +#define PAGE_SIZE 8U +#define SIZE 256U + +#define EEPROM_LC02B_SDA_PORT I2C2_SDA_GPIO_Port +#define EEPROM_LC02B_SDA_PIN I2C2_SDA_Pin +#define EEPROM_LC02B_SCL_PORT I2C2_SCL_GPIO_Port +#define EEPROM_LC02B_SCL_PIN I2C2_SCL_Pin + +static i2c_t *eeprom_24lc028bt_i2c; + +void eeprom_lc02b_test(void) +{ +#define TEST_SIZE 15 + uint16_t test_address = SIZE - TEST_SIZE; + uint8_t buf[TEST_SIZE]; + for (uint8_t i = 0; i < TEST_SIZE; i++) + { + buf[i] = i + 1; + } + + eeprom_lc02b_write(test_address, buf, TEST_SIZE); + delay_ms(10); + osel_memset(buf, 0, ARRAY_LEN(buf)); + eeprom_lc02b_read(test_address, buf, TEST_SIZE); + + __NOP(); +} + +/** + * @brief EEPROM LC02B初始化 + * @return {*} + * @note + */ +void eeprom_lc02b_init(void) +{ + i2c_gpio_group_t gpios; + gpios.scl = gpio_create(EEPROM_LC02B_SCL_PORT, EEPROM_LC02B_SCL_PIN); + gpios.sda = gpio_create(EEPROM_LC02B_SDA_PORT, EEPROM_LC02B_SDA_PIN); + + eeprom_24lc028bt_i2c = i2c_create(gpios, 0); + // eeprom_lc02b_test(); +} + +/** + * @brief EEPROM LC02B反初始化 + * @return {*} + * @note + */ +void eeprom_lc02b_dinit(void) +{ + GPIO_SET_ANALOG(EEPROM_LC02B_SDA_PORT, EEPROM_LC02B_SDA_PIN); + GPIO_SET_ANALOG(EEPROM_LC02B_SCL_PORT, EEPROM_LC02B_SCL_PIN); +} +/** + * @brief 写入数据 + * @param {uint32_t} write_addr + * @param {uint8_t} *data + * @param {uint16_t} length + * @return {*} + * @note + */ +void eeprom_lc02b_write(uint32_t write_addr, uint8_t *data, uint16_t length) +{ + // 发送开始信号 + eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c); + // 发送写入地址命令 + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM); + // 等待写入地址命令响应 + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + // 发送要写入的地址 + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)write_addr); + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + + // 循环写入数据 + + for (uint16_t i = 0; i < length; i++) + { + // 写入一个字节数据 + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, *data++); + // 等待响应 + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + write_addr++; + if (write_addr % PAGE_SIZE == 0) + { + eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c); + delay_ms(10); // 延时10ms,等待写入完成 + eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c); + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM); + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)write_addr); + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + } + } + // 写入完成,停止I2C总线 + eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c); +} + +/** + * @brief 读取数据 + * @param {uint32_t} read_addr + * @param {uint8_t} *data + * @param {uint16_t} length + * @return {*} + * @note + */ +void eeprom_lc02b_read(uint32_t read_addr, uint8_t *data, uint16_t length) +{ + // 发送开始信号 + eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c); + // 发送写入地址命令 + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, W_ADD_COM); + // 等待写入地址命令响应 + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + + // 发送要读取的地址 + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, (uint8_t)read_addr); + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + + // 发送开始信号 + eeprom_24lc028bt_i2c->interface.start(eeprom_24lc028bt_i2c); + // 发送读取地址命令 + eeprom_24lc028bt_i2c->interface.write_byte(eeprom_24lc028bt_i2c, R_ADD_COM); + // 等待读取地址命令响应 + eeprom_24lc028bt_i2c->interface.wait_ack(eeprom_24lc028bt_i2c); + // 循环读取数据 + for (uint16_t i = 0; i < length - 1; i++) + { + // 读取一个字节数据 + *data++ = eeprom_24lc028bt_i2c->interface.read_byte(eeprom_24lc028bt_i2c, TRUE); + } + *data++ = eeprom_24lc028bt_i2c->interface.read_byte(eeprom_24lc028bt_i2c, FALSE); + // 停止I2C总线 + eeprom_24lc028bt_i2c->interface.stop(eeprom_24lc028bt_i2c); +} diff --git a/User/board/src/eeprom_m95.c b/User/board/src/eeprom_m95.c new file mode 100644 index 0000000..f68a68c --- /dev/null +++ b/User/board/src/eeprom_m95.c @@ -0,0 +1,339 @@ +/** + * @file eeprom_m95.c + * @author xxx + * @date 2023-08-30 08:58:43 + * @brief 用于实现M95 EEPROM相关的读写操作 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "eeprom_m95.h" +#include "spis.h" +#include "delay.h" +#include "entity.h" +#include "board.h" +#include "diagnosis.h" + +#define M95_SPI SPI1 +#define M95_DMA DMA1 +#define M95_DMA_RX_CHANNEL LL_DMA_CHANNEL_2 +#define M95_DMA_TX_CHANNEL LL_DMA_CHANNEL_3 + +#define EEPROM_M95_1_CS_PORT EE1_CS_GPIO_Port +#define EEPROM_M95_1_CS_PIN EE1_CS_Pin +#define EEPROM_M95_2_CS_PORT EE2_CS_GPIO_Port +#define EEPROM_M95_2_CS_PIN EE2_CS_Pin + +// 下面宏定义为2个EEPROM_M95的引脚定义 +#define EEPROM_M95_MOSI_PORT SPI_MOSI_GPIO_Port +#define EEPROM_M95_MOSI_PIN SPI_MOSI_Pin +#define EEPROM_M95_MISO_PORT SPI_MISO_GPIO_Port +#define EEPROM_M95_MISO_PIN SPI_MISO_Pin +#define EEPROM_M95_SCK_PORT SPI_CLK_GPIO_Port +#define EEPROM_M95_SCK_PIN SPI_CLK_Pin + +__IO m95_number_e current_m95_number; +m95_number_t eeprom_m95s[M95_MAX]; + +static void write_enable(spi_t *eeprom_m95_spi); // 写使能 +static void write_disable(spi_t *eeprom_m95_spi); // 写保护 +static uint8_t read_status(spi_t *eeprom_m95_spi); // 读状态 +static void eeprom_m95_ready(m95_number_e num); // 等待就绪 + +// DMA TX回调函数 +static void dma_tx_cb(spi_t *handle) +{ + DMA_ClEAR_FLAG(handle->dma, 3, handle->tx_dma_ok); +} + +// DMA RX回调函数 +static void dma_rx_cb(spi_t *handle) +{ + DMA_ClEAR_FLAG(handle->dma, 2, handle->rx_dma_ok); +} + +/** + * @brief 初始化EEPROM_M95eeprom_m95s + * @param {m95_number_e} num + * @return {*} + * @note 初始化函数对板卡上不同的芯片定义了块大小 + */ +void eeprom_m95_init(m95_number_e num) +{ + DBG_ASSERT(num < M95_MAX __DBG_LINE); + current_m95_number = num; + spi_gpio_group_t gpios; + spi_t *eeprom_m95_spi; + // 128 byte + if (num == M95_1) + { + // 创建CS引脚 + gpios.cs = gpio_create(EEPROM_M95_1_CS_PORT, EEPROM_M95_1_CS_PIN); + // 设置页面大小 + eeprom_m95s[num].page_size = M95_PAGE_SIZE_128; + // 设置总大小 + eeprom_m95s[num].total_size = _M95512_; + + eeprom_m95s[num].address_bytes = 2; + } + // 256 byte + else if (num == M95_2) + { + // 创建CS引脚 + gpios.cs = gpio_create(EEPROM_M95_2_CS_PORT, EEPROM_M95_2_CS_PIN); + // 设置页面大小 + eeprom_m95s[num].page_size = M95_PAGE_SIZE_256; + // 设置总大小 + eeprom_m95s[num].total_size = _M95M02_; + + eeprom_m95s[num].address_bytes = 3; + } + else + { + DBG_ASSERT(FALSE __DBG_LINE); + } + + eeprom_m95s[num].rxbuf = (uint8_t *)osel_mem_alloc(eeprom_m95s[num].page_size + (eeprom_m95s[num].address_bytes + 1) * 2); + eeprom_m95s[num].txbuf = (uint8_t *)osel_mem_alloc(eeprom_m95s[num].page_size + eeprom_m95s[num].address_bytes + 1); + + gpios.mosi = gpio_create(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin); + gpios.sck = gpio_create(SPI_CLK_GPIO_Port, SPI_CLK_Pin); + gpios.miso = gpio_create(SPI_MISO_GPIO_Port, SPI_MISO_Pin); + gpios.rst = gpio_create(NULL, 0); + gpios.rdy = gpio_create(NULL, 0); + + // 创建SPI对象 + eeprom_m95_spi = spi_create(SPI_TYPE_NORMAL, gpios, 0); + DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE); + + // 使能SPI + eeprom_m95_spi->interface.hardware_enable(eeprom_m95_spi, M95_SPI); + eeprom_m95_spi->interface.dma_enable(eeprom_m95_spi, M95_DMA, M95_DMA_RX_CHANNEL, dma_rx_cb, M95_DMA_TX_CHANNEL, dma_tx_cb); + eeprom_m95s[num].num = num; + eeprom_m95s[num].spi = eeprom_m95_spi; + // 这里需要设置,否则读出的数据不对 + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); + delay_tick(10); + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); + delay_tick(10); + + // eeprom_m95_test(num); +} + +/** + * @brief 反初始化EEPROM_M95 + * @param {m95_number_e} num + * @return {*} + * @note + */ +void eeprom_m95_dinit(m95_number_e num) +{ + LL_SPI_Disable(M95_SPI); + GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.mosi->port, eeprom_m95s[num].spi->gpios.mosi->pin); + GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.miso->port, eeprom_m95s[num].spi->gpios.miso->pin); + GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.sck->port, eeprom_m95s[num].spi->gpios.sck->pin); + GPIO_SET_ANALOG(eeprom_m95s[num].spi->gpios.cs->port, eeprom_m95s[num].spi->gpios.cs->pin); +} + +/** + * @brief M95 EEPROM使能 + * @return {*} + * @note + */ +void eeprom_m95_enable(void) +{ + LL_SPI_Enable(M95_SPI); +} + +/** + * @brief M95 EEPROM失能 + * @return {*} + * @note + */ +void eeprom_m95_disable(void) +{ + LL_SPI_Disable(M95_SPI); +} + +/** + * @brief 读取M95 EEPROM内存数据 + * @param num EEPROM模块编号(0或1) + * @param read_addr 要读取的地址 + * @param data 存储读取数据的缓冲区 + * @param length 要读取的数据长度 + * @return {*} + */ +void eeprom_m95_read(m95_number_e num, uint32_t read_addr, uint8_t *data, uint16_t length) +{ + current_m95_number = num; + spi_t *eeprom_m95_spi = eeprom_m95s[num].spi; // 获取EEPROM模块的SPI配置 + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为低电平,准备开始SPI通信 + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_READ); // 发送读取命令 + if (eeprom_m95s[num].address_bytes == 2) + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr >> 8); // 发送高位地址 + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr); // 发送低位地址 + } + else + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr >> 16); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr >> 8); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, read_addr); + } + for (uint16_t i = 0; i < length; i++) // 循环读取数据 + { + data[i] = eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_DUMMY_BYTE); // 发送空字节,读取实际数据 + } + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为高电平,完成SPI通信 +} + +/** + * @brief 向M95 EEPROM内存写入数据 + * @param num EEPROM模块编号(0或1) + * @param write_addr 要写入的地址 + * @param data 包含要写入数据的缓冲区 + * @param length 要写入的数据长度 + * @return {*} + */ +void eeprom_m95_write(m95_number_e num, uint32_t write_addr, uint8_t *data, uint16_t length) +{ + current_m95_number = num; + spi_t *eeprom_m95_spi = eeprom_m95s[num].spi; + uint32_t page_size = eeprom_m95s[num].page_size; + DBG_ASSERT(eeprom_m95_spi != NULL __DBG_LINE); + write_enable(eeprom_m95_spi); // 写入使能命令 + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为低电平,准备开始SPI通信 + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WRITE); // 发送写入命令 + + if (eeprom_m95s[num].address_bytes == 2) + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8); // 发送高位地址 + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr); // 发送低位地址 + } + else + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 16); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr); + } + + while (length--) + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, *data); // 发送一个字节数据 + data++; + write_addr++; + if (((write_addr % page_size) == 0) && (length > 0)) + { + // 一页写完 + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为高电平,完成SPI通信 + eeprom_m95_ready(num); + + write_enable(eeprom_m95_spi); // 写入使能命令 + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为低电平,准备开始SPI通信 + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WRITE); // 发送写入命令 + if (eeprom_m95s[num].address_bytes == 2) + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8); // 发送高位地址 + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr); // 发送低位地址 + } + else + { + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 16); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr >> 8); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, write_addr); + } + } + } + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); // 设置CS引脚为高电平,完成SPI通信 + eeprom_m95_ready(num); + write_disable(eeprom_m95_spi); +} + +/** + * @brief 用于M95 EEPROM测试 + * @param {m95_number_e} num + * @return {*} + * @note + */ +void eeprom_m95_test(m95_number_e num) +{ +#define TEST_LEN 10 + DBG_ASSERT(eeprom_m95s[num].spi != NULL __DBG_LINE); + uint16_t test_address = 0; + uint8_t buf[TEST_LEN]; + buf[0] = 0xA5; + buf[1] = 0xC8; + buf[2] = 0x00; + buf[3] = 0x03; + buf[4] = num; + buf[5] = 0xaa; + buf[6] = 0xbb; + buf[TEST_LEN - 1] = 0xce; + eeprom_m95_write(num, test_address, buf, TEST_LEN); + osel_memset(buf, 0, ARRAY_LEN(buf)); + eeprom_m95_read(num, test_address, buf, TEST_LEN); + + __NOP(); +} + +/** + * @brief M95 EEPROM写使能 + * @param {spi_t} *eeprom_m95_spi + * @return {*} + * @note + */ +static void write_enable(spi_t *eeprom_m95_spi) +{ + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WREN); + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); +} + +/** + * @brief M95 EEPROM写保护 + * @param {spi_t} *eeprom_m95_spi + * @return {*} + * @note + */ +static void write_disable(spi_t *eeprom_m95_spi) +{ + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_WRDI); + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); +} + +/** + * @brief M95 EEPROM读状态 + * @param {spi_t} *eeprom_m95_spi + * @return {*} + * @note + */ +static uint8_t read_status(spi_t *eeprom_m95_spi) +{ + uint8_t data; + eeprom_m95_spi->gpios.cs->reset(*eeprom_m95_spi->gpios.cs); + eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_CMD_RDSR); + data = eeprom_m95_spi->interface.u.normal.spi_send(eeprom_m95_spi, M95_DUMMY_BYTE); + eeprom_m95_spi->gpios.cs->set(*eeprom_m95_spi->gpios.cs); + + return data; +} + +/** + * @brief M95 EEPROM等待就绪 + * @param {m95_number_e} num + * @return {*} + * @note + */ +static void eeprom_m95_ready(m95_number_e num) +{ + spi_t *eeprom_m95_spi = eeprom_m95s[num].spi; + uint16_t count = 0; + while (read_status(eeprom_m95_spi) & 0x01) + { + if (count++ > 2000) + { + __NOP(); + break; + } + } +} diff --git a/User/board/src/leds.c b/User/board/src/leds.c new file mode 100644 index 0000000..e420811 --- /dev/null +++ b/User/board/src/leds.c @@ -0,0 +1,170 @@ +#include "leds.h" +#include "gpios.h" + +static gpio_t *leds[LEDS_MAX]; + +/** + * @brief 初始化LED + * @return {*} + * @note + */ +void leds_init(void) +{ + GPIO_SET_OUTPUT(LED1_GPIO_Port, LED1_Pin); + GPIO_SET_OUTPUT(LED2_GPIO_Port, LED2_Pin); + GPIO_SET_OUTPUT(LED3_GPIO_Port, LED3_Pin); + GPIO_SET_OUTPUT(LED4_GPIO_Port, LED4_Pin); + GPIO_SET_OUTPUT(LED5_GPIO_Port, LED5_Pin); + for (uint8_t i = 0; i < LEDS_MAX; i++) + { + if (leds[i] == NULL) + { + switch (i) + { + case LEDS_1_RED: + leds[i] = gpio_create(LED1_GPIO_Port, LED1_Pin); + break; + case LEDS_1_GREEN: + leds[i] = gpio_create(LED2_GPIO_Port, LED2_Pin); + break; + case LEDS_1_YELLOW: + leds[i] = gpio_create(LED3_GPIO_Port, LED3_Pin); + break; + case LEDS_2_ORANGE: + leds[i] = gpio_create(LED4_GPIO_Port, LED4_Pin); + break; + case LEDS_2_BLUE: + leds[i] = gpio_create(LED5_GPIO_Port, LED5_Pin); + break; + default: + break; + } + } + } +} + +/** + * @brief 反初始化LED + * @return {*} + * @note + */ +void leds_dinit(void) +{ + GPIO_SET_ANALOG(LED1_GPIO_Port, LED1_Pin); + GPIO_SET_ANALOG(LED2_GPIO_Port, LED2_Pin); + GPIO_SET_ANALOG(LED3_GPIO_Port, LED3_Pin); + GPIO_SET_ANALOG(LED4_GPIO_Port, LED4_Pin); + GPIO_SET_ANALOG(LED5_GPIO_Port, LED5_Pin); +} + +/** + * @brief 打开LED + * @param {leds_e} io + * @return {*} + * @note + */ +void leds_on(leds_e io) +{ + switch (io) + { + case LEDS_1_RED: + GPIO_SET_OUTPUT(LED1_GPIO_Port, LED1_Pin); + break; + case LEDS_1_GREEN: + GPIO_SET_OUTPUT(LED2_GPIO_Port, LED2_Pin); + break; + case LEDS_1_YELLOW: + GPIO_SET_OUTPUT(LED3_GPIO_Port, LED3_Pin); + break; + case LEDS_2_ORANGE: + GPIO_SET_OUTPUT(LED4_GPIO_Port, LED4_Pin); + break; + case LEDS_2_BLUE: + GPIO_SET_OUTPUT(LED5_GPIO_Port, LED5_Pin); + break; + default: + break; + } + if (io < LEDS_MAX) + { + leds[(uint8_t)io]->reset(*leds[(uint8_t)io]); + } +} + +/** + * @brief 打开所有LED + * @return {*} + * @note + */ +void leds_on_all(void) +{ + leds_on(LEDS_1_RED); + leds_on(LEDS_1_GREEN); + leds_on(LEDS_1_YELLOW); + leds_on(LEDS_2_ORANGE); + leds_on(LEDS_2_BLUE); +} + +/** + * @brief 关闭LED + * @param {leds_e} io + * @return {*} + * @note + */ +void leds_off(leds_e io) +{ + if (io < LEDS_MAX) + { + leds[(uint8_t)io]->set(*leds[(uint8_t)io]); + } + + // 反初始化其他LED,这里暂时先不做处理,如果电流不够,可以考虑关闭其他LED + // switch (io) + // { + // case LEDS_1_RED: + // GPIO_SET_ANALOG(LED1_GPIO_Port, LED1_Pin); + // break; + // case LEDS_1_GREEN: + // GPIO_SET_ANALOG(LED2_GPIO_Port, LED2_Pin); + // break; + // case LEDS_1_YELLOW: + // GPIO_SET_ANALOG(LED3_GPIO_Port, LED3_Pin); + // break; + // case LEDS_2_ORANGE: + // GPIO_SET_ANALOG(LED4_GPIO_Port, LED4_Pin); + // break; + // case LEDS_2_BLUE: + // GPIO_SET_ANALOG(LED5_GPIO_Port, LED5_Pin); + // break; + // default: + // break; + // } +} + +/** + * @brief 关闭所有LED + * @return {*} + * @note + */ +void leds_off_all(void) +{ + leds_off(LEDS_1_RED); + leds_off(LEDS_1_GREEN); + leds_off(LEDS_1_YELLOW); + leds_off(LEDS_2_ORANGE); + leds_off(LEDS_2_BLUE); +} + +/** + * @brief 翻转LED + * @param {leds_e} io + * @return {*} + * @note + */ +void leds_toggle(leds_e io) +{ + if (io < LEDS_MAX) + { + leds[(uint8_t)io]->toggle(*leds[(uint8_t)io]); + } +} diff --git a/User/board/src/ntc_3950.c b/User/board/src/ntc_3950.c new file mode 100644 index 0000000..fe6538b --- /dev/null +++ b/User/board/src/ntc_3950.c @@ -0,0 +1,107 @@ +/** + * @file ntc_3950.c + * @author xxx + * @date 2023-08-30 08:58:43 + * @brief 用于实现NTC的应用功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "ntc_3950.h" +#define CPU_VREF 2.5 +#define NTC_VREF 3.0 +#define TABLE_SIZE 185 +#define NTC_SERIES_RESISTOR 200000 ///< 200K +#define BASE_TEMP -55 + +const uint32_t _table[TABLE_SIZE] = { + 8989000, 8242680, 7592960, 7021380, 6513750, // -55,-54,-53,-52,-51 + 6059060, 5648680, 5275800, 4935020, 4621990, 4333220, 4065840, 3817520, 3586310, 3370600, // -50,-49,-48,-47,-46,-45,-44,-43,-42,-41 + 3169000, 2980330, 2803600, 2637910, 2482470, 2336580, 2199620, 2071020, 1950230, 1836790, // -40,-39,-38,-37,-36,-35,-34,-33,-32,-31 + 1730230, 1630150, 1536140, 1447840, 1364900, 1287000, 1213820, 1145090, 1080530, 1019890, // -30,-29,-28,-27,-26,-25,-24,-23,-22,-21 + 962912, 909379, 859074, 811797, 767359, 725581, 686296, 649348, 614590, 581883, // -20,-19,-18,-17,-16,-15,-14,-13,-12,-11 + 551100, 522117, 494824, 469113, 444886, 422050, 400518, 380209, 361048, 342963, // -10,-9,-8,-7,-6,-5,-4,-3,-2,-1 + 326560, 309764, 294529, 280131, 266520, 253647, 241470, 229946, 219036, 208706, // 0,1, 2, 3,4,5,6,7,8,9 + 198920, 189647, 180857, 172523, 164618, 157118, 150000, 143243, 136827, 130731, // 10,11 ,12, 13,14,15,16,17,18,19 + 124940, 119435, 114202, 109225, 104491, 100000, 95699, 91617, 87731, 84028, // 20,21, 22, 23,24,25,26,27,28,29 + 80501, 77140, 73936, 70881, 67968, 65188, 62537, 60006, 57590, 55283, // 30,31, 32, 33,34,35,36,37,38,39 + 53080, 50976, 48965, 47044, 45207, 43451, 41771, 40165, 38628, 37157, // 40,41, 42, 43,34,35,36,37,38,39 + 35750, 34402, 33112, 31876, 30692, 29558, 28471, 27429, 26430, 25472, // 50,51, 52, 53,54,55,56,57,58,59 + 24554, 23672, 22827, 22016, 21237, 20489, 19771, 19082, 18420, 17784, // 60,61, 62, 63,64,65,66,67,68,69 + 17172, 16585, 16020, 15477, 14955, 14453, 13970, 13505, 13058, 12628, // 70,71, 72, 73,74,75,76,77,78,79 + 12213, 11815, 11431, 11061, 10705, 10362, 10031, 9712, 9405, 9110, // 80,81, 82, 83,84,85,86,87,88,89 + 8824, 8549, 8284, 8028, 7782, 7544, 7314, 7093, 6879, 6673, // 90,91, 92, 93,94,95,96,97,98,99 + 6474, 6281, 6096, 5916, 5743, 5576, 5415, 5259, 5108, 4963, // 101,102, 103,104,105,106,107,108,109 + 4822, 4687, 4555, 4428, 4306, 4187, 4073, 3962, 3855, 3751, // 111,112, 113,114,115,116,117,118,119 + 3651, 3555, 3461, 3371, 3283, 3199, 3100, 3099, 2899, 2799, // 121,122, 123,124,125,126,127,128,129 +}; + +/** + * @brief 温度查表 + * @param {uint32_t} *list + * @param {uint32_t} rt + * @return {*} + * @note + */ +static uint8_t ntc_lookup(const uint32_t *list, uint32_t rt) +{ + uint8_t middle = 0; + uint8_t indexL = 0; + uint8_t indexR = TABLE_SIZE - 1; + if (rt >= *(list + 0)) + return 0; + if (rt <= *(list + TABLE_SIZE - 1)) + return TABLE_SIZE - 1; + + while ((indexR - indexL) > 1) + { + middle = (indexL + indexR) >> 1; + if (rt == *(list + middle)) + return middle; + else if (rt > *(list + middle)) + indexR = middle; + else if (rt < *(list + middle)) + indexL = middle; + } + return indexL; +} + +/** + * @brief 获取温度值,单位为0.1摄氏度 + * @param {uint16_t} adc采集值 + * @return {float32_u} 温度值 + * @note + */ +float32_u ntc_get_temp(uint16_t adc) +{ + + uint8_t index = 0; + int16_t data = 0; + int16_t t = 0; + int16_t result = 0; + uint32_t rt = 0; + const int16_t base = BASE_TEMP * 10; + float32_u res; + res.f = BASE_TEMP; + + /** + * ad = (4095*rt)/(rt+10000) + * + * rt = (ad*NTC_SERIES_RESISTOR*CPU_VREF)/(NTC_VREF*4095-CPU_VREF*ad) + */ + rt = (adc * NTC_SERIES_RESISTOR * CPU_VREF) / (NTC_VREF * 4095 - CPU_VREF * adc); + index = ntc_lookup(_table, rt); + if (rt >= _table[0]) + return res; + if (rt <= *(_table + TABLE_SIZE - 1)) + { + result = (TABLE_SIZE - 1) * 10 + base; + } + else + { + data = _table[index] - _table[index + 1]; + t = 10 * (_table[index] - rt) / data; + result = base + index * 10 + t; + } + res.f = result / 10.0; + return res; +} diff --git a/User/board/src/rtc_rx8010.c b/User/board/src/rtc_rx8010.c new file mode 100644 index 0000000..7953bf1 --- /dev/null +++ b/User/board/src/rtc_rx8010.c @@ -0,0 +1,513 @@ +/** + * @file rtc_rx8010.c + * @author xxx + * @date 2023-08-30 08:58:43 + * @brief 用于实现RTC芯片RX8010的应用功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "rtc_rx8010.h" +#include "i2cs.h" +#include "delay.h" + +#define RTC_RX8010_SDA_PORT RTC_SDA_GPIO_Port +#define RTC_RX8010_SDA_PIN RTC_SDA_Pin +#define RTC_RX8010_SCL_PORT RTC_SCL_GPIO_Port +#define RTC_RX8010_SCL_PIN RTC_SCL_Pin + +static i2c_t *rtc; + +/* sec, min, hour, week, day, month, year */ +// static uint8_t calendar[7] = {0, 0, 0, 1, 29, 2, 98}; + +/** + * @brief 从RTC芯片的指定地址读取一个字节数据 + * @param {uint8_t} *read_buf + * @param {uint8_t} addr + * @return {*} + */ +static BOOL rtc_read_byte(uint8_t *read_buf, uint8_t addr) +{ + uint8_t *p = read_buf; + + /* 发送起始信号 */ + rtc->interface.start(rtc); + + /* 发送从机地址 + 读写方向 */ + rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 此处是写方向,因为要发送读地址 */ + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 发送读地址 */ + rtc->interface.write_byte(rtc, addr); + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 重新发送起始信号。前面的代码的目的向RTC传送地址,下面开始读取数据 */ + rtc->interface.start(rtc); + + /* 发送从机地址 + 读写方向 */ + rtc->interface.write_byte(rtc, RTC_RD_ADDR); /* 此处是读方向,因为要开始读数据了 */ + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + /* 读取数据 */ + *p = rtc->interface.read_byte(rtc, FALSE); /* 读1个字节 */ + + /* 命令执行成功,发送I2C总线停止信号 */ + rtc->interface.stop(rtc); + return TRUE; +} + +/** + * @brief 从RTC芯片的指定地址读取若干数据 + * @param {uint8_t} *read_buf + * @param {uint8_t} addr + * @param {int} size + * @return {*} + */ +static BOOL rtc_read_bytes(uint8_t *read_buf, uint8_t addr, int size) +{ + int i = 0; + + /* 发送起始信号 */ + rtc->interface.start(rtc); + + /* 发送从机地址 + 读写方向 */ + rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 此处是写方向,因为要发送读地址 */ + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 发送读地址 */ + rtc->interface.write_byte(rtc, addr); + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 重新发送起始信号。前面的代码的目的向RTC传送地址,下面开始读取数据 */ + rtc->interface.start(rtc); + + /* 发送从机地址 + 读写方向 */ + rtc->interface.write_byte(rtc, RTC_RD_ADDR); /* 此处是读方向,因为要开始读数据了 */ + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 循环读取数据,RTC芯片地址自动自增 */ + for (i = 0; i < size; i++) + { + /* 每读完1个字节后,需要发送Ack, 最后一个字节需要发Nack */ + if (i != (size - 1)) + { + read_buf[i] = rtc->interface.read_byte(rtc, TRUE); /* 读1个字节 */ + } + else + { + read_buf[i] = rtc->interface.read_byte(rtc, FALSE); /* 读1个字节 */ + } + } + + /* 命令执行成功,发送I2C总线停止信号 */ + rtc->interface.stop(rtc); + return TRUE; +} + +/** + * @brief 向RTC芯片的指定地址写入一个数据 + * @param {uint8_t} data + * @param {uint8_t} addr + * @return {*} + * @note + */ +static BOOL rtc_write_byte(uint8_t data, uint8_t addr) +{ + int retry = 0; + + /* 尝试与RTC芯片建立I2C通讯 */ + for (retry = 0; retry < 100; retry++) + { + rtc->interface.start(rtc); /* 发送起始信号 */ + rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 发送从机地址 + 读写方向 */ + if (rtc->interface.wait_ack(rtc) == TRUE) + { + break; + } + } + if (retry == 100) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 发送起始写地址 */ + rtc->interface.write_byte(rtc, addr); + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 写入数据 */ + rtc->interface.write_byte(rtc, data); + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 命令执行成功,发送I2C总线停止信号 */ + rtc->interface.stop(rtc); + return TRUE; +} + +/** + * @brief 向RTC芯片的指定地址写入若干数据 + * @param {uint8_t} *write_buf + * @param {uint8_t} addr + * @param {int} size + * @return {*} + * @note + */ +static BOOL rtc_write_bytes(uint8_t *write_buf, uint8_t addr, int size) +{ + int i = 0; + int retry = 0; + + for (i = 0; i < size; i++) + { + if (i == 0) + { + /* 尝试与RTC芯片建立I2C通讯 */ + for (retry = 0; retry < 100; retry++) + { + rtc->interface.start(rtc); /* 发送起始信号 */ + rtc->interface.write_byte(rtc, RTC_WR_ADDR); /* 发送从机地址 + 读写方向 */ + if (rtc->interface.wait_ack(rtc) == TRUE) + { + break; + } + } + if (retry == 100) + { + rtc->interface.stop(rtc); + return FALSE; + } + + /* 发送起始写地址 */ + rtc->interface.write_byte(rtc, addr); + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + } + + /* 循环写入数据,RTC芯片地址自动自增 */ + rtc->interface.write_byte(rtc, write_buf[i]); + if (rtc->interface.wait_ack(rtc) != TRUE) + { + rtc->interface.stop(rtc); + return FALSE; + } + } + + /* 命令执行成功,发送I2C总线停止信号 */ + rtc->interface.stop(rtc); + return TRUE; +} + +/** + * @brief 假读RTC芯片,任意读地址,不判断RTC响应 + * @return {*} + * @note + */ +static void rtc_dummy_read(void) +{ + rtc->interface.start(rtc); + rtc->interface.write_byte(rtc, RTC_WR_ADDR); + rtc->interface.write_byte(rtc, 0x20); + + rtc->interface.start(rtc); + rtc->interface.write_byte(rtc, RTC_RD_ADDR); + rtc->interface.read_byte(rtc, FALSE); + + rtc->interface.stop(rtc); +} + +/** + * @brief 用于检查VLF,寄存器地址:0x1e bit[1] + * @return {uint8_t} 0 = VLF位为0,1 = VLF位为1 + * @note + */ +static uint8_t rtc_check_vlf(void) +{ + uint8_t flag_register = 1; + uint8_t vlf = 0; + + rtc_read_byte(&flag_register, RTC_FLAG_ADDR); + + vlf = (flag_register & 0x02); + if (vlf == 0) + { + return 0; + } + else + { + return 1; + } +} + +/** + * @brief 等待VLF位清除,寄存器地址:0x1e bit[1] + * @return {uint8_t} 0 = 清零成功,1 = 清零失败,2 = 无需清零 + */ +static uint8_t rtc_wait_vlf_clear(void) +{ + uint8_t ret = 1; + uint8_t i = 0; + uint8_t vlf; + + for (i = 0; i < 10; i++) + { + vlf = rtc_check_vlf(); + + if (vlf == 0) + { + ret = ((i > 0) ? 0 : 2); + return ret; + } + + /* 清除VLF */ + rtc_write_byte(0, RTC_FLAG_ADDR); + } + + return ret; +} + +/** + * @brief 复位 + * @return {BOOL} FALSE = 复位成功,TRUE = 复位失败 + */ +static BOOL rtc_soft_reset(void) +{ + BOOL ret = FALSE; + + ret = rtc_write_byte(0x00, 0x1f); + ret = rtc_write_byte(0x80, 0x1f); + ret = rtc_write_byte(0xd3, 0x60); + ret = rtc_write_byte(0x03, 0x66); + ret = rtc_write_byte(0x02, 0x6b); + ret = rtc_write_byte(0x01, 0x6b); + + if (ret == 0) + { + delay_ms(2); + } + + return ret; +} + +/** + * @brief 时钟寄存器初始化函数 + * @return {BOOL} TRUE = 初始化成功,FALSE = 初始化失败 + */ +static BOOL rtc_clock_reginit(void) +{ + BOOL ret = FALSE; + + /* set reserve register */ + ret = rtc_write_byte(RTC_REG17_DATA, RTC_REG17_ADDR); + ret = rtc_write_byte(RTC_REG30_DATA, RTC_REG30_ADDR); + ret = rtc_write_byte(RTC_REG31_DATA, RTC_REG31_ADDR); + ret = rtc_write_byte(RTC_IRQ_DATA, RTC_IRQ_ADDR); + /* write 0x04 to reg_0x1d */ + ret = rtc_write_byte(0x04, 0x1d); + /* write 0x00 to reg_0x1e */ + ret = rtc_write_byte(0x00, 0x1e); + /* stop clock */ + ret = rtc_write_byte(0x40, RTC_CONTROL_ADDR); + /* set the present time */ + // ret = rtc_write_bytes(calendar, RTC_CLOCK_ADDR, sizeof(calendar)); + /* start clock */ + ret = rtc_write_byte(0x00, RTC_CONTROL_ADDR); + + return ret; +} + +/** + * @brief RTC芯片初始化 + * @return {BOOL} TRUE = 成功,FALSE = 失败 + * @note + */ +BOOL rtc_init(void) +{ + i2c_gpio_group_t gpios; + int ret = 1; + gpios.scl = gpio_create(RTC_RX8010_SCL_PORT, RTC_RX8010_SCL_PIN); + gpios.sda = gpio_create(RTC_RX8010_SDA_PORT, RTC_RX8010_SDA_PIN); + + rtc = i2c_create(gpios, 50); + + rtc_dummy_read(); + /* wait for VLF bit clear */ + ret = rtc_wait_vlf_clear(); + if (ret == 0) + { + /* software reset */ + ret = rtc_soft_reset(); + if (ret == FALSE) + { + return FALSE; + } + } + else if (ret == 1) + { + return FALSE; + } + + /* register initialize */ + + return rtc_clock_reginit(); +} + +/** + * @brief RTC芯片反初始化 + * @return {*} + * @note + */ +BOOL rtc_dinit(void) +{ + GPIO_SET_ANALOG(RTC_RX8010_SCL_PORT, RTC_RX8010_SCL_PIN); + GPIO_SET_ANALOG(RTC_RX8010_SDA_PORT, RTC_RX8010_SDA_PIN); + return TRUE; +} + +/** + * @brief 从RTC芯片读取时间 + * @param {uint8_t} *read_buf - 接收缓存指针,用于接收读取到的数据 + * @return {BOOL} TRUE = 成功,FALSE = 失败 + * @note + */ +BOOL rtc_get_clock_time(uint8_t *read_buf) +{ + return rtc_read_bytes(read_buf, RTC_CLOCK_ADDR, 7); +} + +/** + * @brief 向RTC芯片写入时间 + * @param {rtc_date} *data - 发送缓存指针,用于存储要发送的数据 + * @return {BOOL} TRUE = 成功,FALSE = 失败 + * @note + */ +BOOL rtc_set_clock_time(rtc_date *data) +{ + BOOL ret = FALSE; + uint8_t tmp[7]; + tmp[0] = data->second; + tmp[1] = data->minute; + tmp[2] = data->hour; + tmp[3] = data->weekday; + tmp[4] = data->day; + tmp[5] = data->month; + tmp[6] = data->year; + + tmp[3] = (rtc_week_e)tmp[3]; // 改成星期几 + + /* stop clock */ + ret = rtc_write_byte(0x40, RTC_CONTROL_ADDR); + /* set the present time */ + ret = rtc_write_bytes(tmp, RTC_CLOCK_ADDR, sizeof(tmp)); + /* start clock */ + ret = rtc_write_byte(0x00, RTC_CONTROL_ADDR); + + return ret; +} + +/** + * @brief 将星期转为星期码 + * @param {uint8_t} *weekday 星期几 + * @return {*} + * @note + */ +void rtc_weekday_convert(uint8_t *weekday) +{ + switch (*weekday) + { + case 1: + *weekday = MON; + break; + case 2: + *weekday = TUE; + break; + case 3: + *weekday = WED; + break; + case 4: + *weekday = THUR; + break; + case 5: + *weekday = FRI; + break; + case 6: + *weekday = SAT; + break; + case 7: + *weekday = SUN; + break; + default: + *weekday = 0; + break; + } +} + +/** + * @brief 将星期码转为星期 + * @param {uint8_t} *weekday 星期码 + * @return {*} + * @note + */ +void rtc_weekday_rconvert(uint8_t *weekday) +{ + switch (*weekday) + { + case MON: + *weekday = 1; + break; + case TUE: + *weekday = 2; + break; + case WED: + *weekday = 3; + break; + case THUR: + *weekday = 4; + break; + case FRI: + *weekday = 5; + break; + case SAT: + *weekday = 6; + break; + case SUN: + *weekday = 7; + break; + default: + *weekday = 0; + break; + } +} diff --git a/User/entity.h b/User/entity.h new file mode 100644 index 0000000..3be0491 --- /dev/null +++ b/User/entity.h @@ -0,0 +1,438 @@ +#ifndef __ENTITY_H__ +#define __ENTITY_H__ +#include "lib.h" +#include "adcs.h" +#include "pid.h" +#include "params.h" +#include "pdctrl.h" +#include "mode.h" + +#define CPU_ENCRYPT_ENABLE FALSE // 是否启用加密 +#define H24_BLE_OUTPUT_DBG TRUE // 是否运行蓝牙输出数据到VOFA上位机 +#define LCD_DESIGN FALSE // 是否运行LCD设计,TRUE模式下程序会跳过一些初始化操作,直接进入LCD设计模式 + +// 硬件版本号 1个字节 +#ifdef V4 +#define HW_VER 0x04 +#elif V5 +#define HW_VER 0x05 +#else +#define HW_VER 0x00 +#endif +// 软件版本号 1个字节 +#define SW_VER 0x01 +// 固件版本号 1个字节 +#define FW_VER 0x03 + +#define HART_VERSION HART_PROTOCOL_VERSION_7 ///< HART协议版本号 +#define CPU_VREF 2.5f ///< CPU基准电压 +#define CPU_UGAGE_MAX 90.0f ///< CPU使用率最大值 +#define MEM_UGAGE_MAX 90.0f ///< 内存使用率最大值 +#define INPUT_CURRENT_MIN 3.8f ///< 输入电流下限3.8mA +#define BLE_CURRENT_WORK 7.9f ///< 蓝牙工作电流 +#define LOOP_CURRENT_MIN 4.0f ///< 输入电流最小值 +#define LOOP_CURRENT_MAX 20.0f ///< 输入电流最大值 +#define LOOP_CURRENT_WORK_MAX 12.0f ///< 工作输出最大电流下限 +#define LCD_WORK_TEMP_MIN -20 ///< LCD最低工作稳定-20℃ +#define BAROMETER_MAX 10 ///< 气压表最大值 + +#define SELF_VCHART_LEN 17 ///< 自定义阀门特性长度 +#define VALVE_SERIAL_NUM_LEN 16 ///< 阀门序列号长度 +#define INST_SERIAL_NUM_LEN 16 ///< 定位器序列号长度 +#define OPERATOR_NAME_LEN 26 ///< 操作员姓名长度 +#define PASSWORD_LEN 4 ///< LCD主菜单页面进入密码长度 +/** + * ADC通道定义: 主频4、分频系数16,根据公式 TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数) 计算每个通道单个采集时间 + * ADC_LOOP_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us + * ADC_PSB_CHANNEL: 47.5+12.5=60个周期,60/(4/16)=240us + * ADC_BP_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us + * ADC_IPSB_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us + * ADC_NTC_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us + * ADC_VIP_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us + * ADC_DCDC_CHANNEL: 640.5+12.5=653个周期,653/(4/16)=2612us + * ADC_BPA_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us + * ADC_BPB_CHANNEL: 47.5+12.5=653个周期,60/(4/16)=240us + * + * 通道采集数量为30个,单个采集时间为240us,总共采集时间为30*240=7200us = 7.2ms + */ +typedef enum +{ + ADC_LOOP_CHANNEL = 0, ///< IN5 输入电流ADC通道 + ADC_PSB_CHANNEL, ///< IN6 阀位反馈ADC通道 + ADC_BP_CHANNEL, ///< IN7 压力传感器ADC通道 + ADC_IPSB_CHANNEL, ///< IN8 内部I/P位置电压(小回路) + ADC_NTC_CHANNEL, ///< IN9 温度ADC电压 + ADC_VIP_CHANNEL, ///< IN11 I/P输出电流 + ADC_DCDC_CHANNEL, ///< IN12 DCDC检测通道 + ADC_BPA_CHANNEL, ///< IN13 A路压力 + ADC_BPB_CHANNEL, ///< IN14 B路压力 + ADC_INVREF_CHANNEL, ///< 内部参考电压 + ADC_TEMP_CHANNEL, ///< 内部参考温度 + + // 下面的定义和ADC中的存储没有关系 + ADC_FLOW, ///< 流量传感器 + ADC1_MAX, ///< ADC1通道最大数量 +} adc1_channel_e; + +/** + * ADC2 :慢速通道单采集 + * ADC_LOOP_CHANNEL: 640.5+12.5=653个周期,653/(4/64)= 10448us + * ADC_PSB_CHANNEL: 640.5+12.5=653个周期,653/(4/64) = 10448us + */ +typedef enum +{ + ADC2_LOOP_CHANNEL = 0, ///< IN5 输入电流ADC通道 + ADC2_PSB_CHANNEL, ///< IN6 阀位反馈ADC通道 + ADC2_MAX, ///< ADC2通道最大数量 +} adc2_channel_e; + +// 校准参数信息 +typedef enum +{ + CALIBPARA_LOOP = 0, ///< 4~20mA采集校准参数 + CALIBPARA_PSB = 1, ///< 位置反馈校准参数 + CALIBPARA_PS = 2, ///< 气源压力校准参数 + CALIBPARA_PA = 3, ///< A输出压力校准参数 + CALIBPARA_PB = 4, ///< B输出压力校准参数 + CALIBPARA_IPSB = 5, ///< 小回路校准参数 + CALIBPARA_VIP = 6, ///< 4~20mA输出校准参数 + CALIBPARA_NUM = 7, ///< 校准参数数量 +} calibration_e; + +// 任务流程状态机 +typedef enum +{ + FLOW_EVENT_NORMAL, ///< 正常任务流程 + FLOW_EVENT_DIAGNOSIS, ///< 诊断任务流程 +} flow_event_e; + +#pragma pack(1) // 编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式 + +/// 时间结构 +typedef union +{ + uint8_t Byte[6]; + + struct + { + uint8_t Year; + uint8_t Month; + uint8_t Day; + uint8_t Hour; + uint8_t Minute; + uint8_t Second; + } Date; +} uDateTime_TypeDef; + +/// 参数校准 +typedef struct +{ + BOOL is_calibration; ///< 是否校准 + float32 value[2]; ///< 校准参数 +} calib_param_t; + +/// 设备基础参数 +typedef struct +{ + // 定位器序列号 + uint8_t dev_serial_num[INST_SERIAL_NUM_LEN]; + // 定位器版本号 + uint32_t dev_version; + // 定位器硬件版本号 + uint8_t dev_hw_version; + // 定位器软件版本号 + uint8_t dev_fw_version; + // 定位器型号 + uint16_t dev_model; + // 定位器HART短地址(轮询地址)(作废,从HART模块获取) + // uint8_t dev_hart_addr; + // 定位器作用方向:正作用/反作用 + uint8_t dev_driver_dir; + // 定位器安装方向 + // 0 = 反向安装,磁条反馈ADC值上小下大 + // 1 = 正向安装,磁条反馈ADC值上大下小 + uint8_t dev_install_dir; + // 定位器工作模式 + // 0 = 自动模式,根据4~20mA控制阀位 + // 1 = 手动模式,根据设定目标值控制阀位 + // 2 = 测试模式,在测试定位器部分功能时,必须在测试模式下进行 + // 3 = 非投用模式,阀门复位,定位器禁用信号控制功能 + // 4 = 待机模式,阀门保持,定位器禁用信号控制功能 + uint8_t dev_work_mode; + // 定位器算法模式 详见:mode_algorithm_e + uint8_t dev_algorithm_mode; + // 定位器控制模式 1 = 位置控制模式,2 = 压力控制模式 + uint8_t dev_ctrl_mode; + // 执行机构类型 + uint8_t value_type; + // 执行机构尺寸 + uint8_t valve_size; + // 执行机构行程 + uint8_t value_travel; + // 自定义执行机构行程 + uint8_t self_value_travel; + // 执行机构行程类型:直行程/角行程 + uint8_t value_travel_type; + // 执行机构气动类型:气开/气关 + uint8_t value_action_type; + // 执行机构作用类型:单作用/双作用 + uint8_t value_relay_type; + // 阀门特性 + uint8_t valve_chart; + // 自定义阀门特性 + uint16_t self_value_chart[SELF_VCHART_LEN]; + // 磁条规格 + uint8_t magnet_spec; + // 写入保护禁用/使能 + uint8_t write_protect_enable; + // 压力传感器使能 + uint8_t press_sensor_enable; + // 增速器禁用/使能 + uint8_t speed_increaser_enable; + // 快排阀禁用/使能 + uint8_t quick_exhaust_enable; + // 无线通讯禁用/使能 + uint8_t wireless_enable; + // PWM输出电流禁用/使能 + uint8_t output_current_enable; + // 输出开关触发逻辑 + uint8_t swo_logic[2]; + // 输出开关触发位置 + float32 swo_value[2]; + // LCD显示方向:0/180 + uint8_t display_direction; + // LCD显示语言 + uint8_t display_language; + // 行程百分比显示方式 + // 0 = 正向显示,与阀门开度一致 + // 1 = 反向显示,与阀门开度相反 + uint8_t display_travel_mode; + // 报警处理方式 + uint8_t alarm_handle_mode; + // 复位处理方式 + uint8_t reset_handle_mode; + // 温度单位 + uint8_t temperature_unit; + // 电流单位 + uint8_t current_unit; + // 行程单位 + uint8_t travel_unit; + // 压力单位 + uint8_t press_unit; + // 力学单位(摩擦力/弹簧力) + uint8_t force_unit; + // 死区(%),表示在目标位置附近设置的可允许偏差。若阀门填料的摩擦力较大,可相应调整并设置此数值, + // 以防止因摩擦导致循环受限。若死区设置为0.5%,则其对应范围为目标的±0.5%。 + float32 travel_dead; // 0.1~10.0% + // 模拟输入范围上限,单位:mA + float32 input_upper; + // 模拟输入范围下限,单位:mA + float32 input_lower; + // 温度范围上限,单位:摄氏度 + float32 temp_upper; + // 温度范围下限,单位:摄氏度 + float32 temp_lower; + // 供应压力范围上限,单位:kpa + float32 supply_upper; + // 供应压力范围下限,单位:kpa + float32 supply_lower; + // 摩擦力范围上限 + float32 friction_upper; + // 摩擦力范围下限 + float32 friction_lower; + // 弹簧力范围上限 + float32 elasticity_upper; + // 弹簧力范围下限 + float32 elasticity_lower; + // 行程范围上限,单位:百分比 + float32 travel_upper; + // 行程范围下限,单位:百分比 + float32 travel_lower; + // 行程报警死区:行程回归超过死区,认为回归正常范围 + float32 travel_alert_dead; + // 小信号切除禁用/使能 + uint8_t travel_cut_enable; + // 小信号上限 + float32 travel_cut_upper; + // 小信号下限 + float32 travel_cut_lower; + // 分程控制禁用/使能 + uint8_t part_travel_enable; + // 分程控制上限 + float32 part_travel_upper; + // 分程控制下限 + float32 part_travel_lower; + // 累计行程上限 + float32 travel_sum_upper; + // 累计行程死区:行程超过累计行程死区时,计算累计行程 + float32 travel_sum_dead; + // 动作次数上限 + uint32_t act_sum_upper; + // 动作次数死区:行程超过动作次数死区时,计算动作次数 + float32 act_sum_dead; + // 供应压力 + float32 supply_press; + // 供应压力偏差(百分比) + float32 supply_error; + // 供应压力偏差报警等待时间 + uint16_t supply_error_time; + // 参考电压 + float32 vref; + // 参考电压偏差 + float32 vref_error; + // 参考电压偏差报警等待时间 + uint16_t vref_error_time; + // 行程偏差 + float32 travel_error; + // 行程偏差报警等待时间(秒)(偏差超出范围的持续时间上限) + uint16_t travel_error_time; + // 阀门打开(上行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec] + float32 travel_rate_open; + // 阀门关闭(下行)变化速率 (%/秒),如需在5秒钟左右移动100%行程,请将其设置为 20 [%/sec] + float32 travel_rate_close; + // 阀门全开时间 + uint16_t all_open_time; + // 阀门全关时间 + uint16_t all_close_time; + // 阀门0位置行程反馈ADC值 + uint16_t pos0_travel_vol; + // 阀门100位置行程反馈ADC值 + uint16_t pos100_travel_vol; + // 阀门0位置小回路反馈ADC值 + uint16_t pos0_minor_vol; + // 阀门100位置小回路反馈ADC值 + uint16_t pos100_minor_vol; + // 阀门0位置A路气压反馈ADC值 + uint16_t pos0_press_a_vol; + // 阀门100位置A路气压反馈ADC值 + uint16_t pos100_press_a_vol; + // 阀门0位置B路气压反馈ADC值 + uint16_t pos0_press_b_vol; + // 阀门100位置B路气压反馈ADC值 + uint16_t pos100_press_b_vol; + // 驱动阀门动作所需上限值 + uint16_t output_max; + // 驱动阀门动作所需下限值 + uint16_t output_min; + // 整定标志 0:未整定,1:整定中,2:整定成功,3:整定失败 + uint8_t tuned_flag; + // PID参数选择,0 = 自适应,1 = 自定义 + uint8_t pid_index; + // 自适应PID参数 + float32 apid_kp; + float32 apid_ki; + float32 apid_kd; + float32 apid_dead; + // 自定义PID参数 + float32 spid_kp; + float32 spid_ki; + float32 spid_kd; + float32 spid_dead; + // PWM输出电流校验4ma采样值 + uint16_t output_4ma_duty; + // PWM输出电流标定20ma采样值 + uint16_t output_20ma_duty; + // 输入电流ADC原始值 + uint16_t input_raw; + // 输入电流偏移 + uint16_t input_offset; + // 输入电流跨度 + uint16_t input_span; + // 气源压力ADC原始值 + uint16_t press_s_raw; + // 气源压力偏移 + uint16_t press_s_offset; + // 气源压力跨度 + uint16_t press_s_span; + // A路压力ADC原始值 + uint16_t press_a_raw; + // A路压力偏移 + uint16_t press_a_offset; + // A路压力跨度 + uint16_t press_a_span; + // B路压力ADC原始值 + uint16_t press_b_raw; + // B路压力偏移 + uint16_t press_b_offset; + // B路压力跨度 + uint16_t press_b_span; + // 记录存储间隔时间(秒) + uint16_t save_cycle; + // 配置时间(时间戳) + uint32_t operating_time; + // 配置人员 + uint8_t operator[OPERATOR_NAME_LEN]; + // 行程设定点 + float32 travel_setpoint; + // LCD主菜单页面进入密码长度 + uint8_t menus_main_password[PASSWORD_LEN]; +} device_typedef; + +/// 设备实时参数 +typedef struct +{ + __IO uint32_t travel_cnt; // 累计行程 + __IO uint32_t act_cnt; // 动作次数 + __IO uint32_t dev_work_time; // 设备工作时长 + __IO uint32_t power_on_cnt; // 设备上电次数 + uint8_t last_dev_variable; // 上一个设备变量 + uint16_t cfg_update_cnt; // 配置更新次数 + __IO uDateTime_TypeDef real_time; // 实时时间 +} rt_save_param_t; + +typedef struct +{ + __IO uint8_t tuned_id; // 整定步骤 + __IO uint16_t ip_output; // IP输出值 + __IO float32 temperature; // 设备温度 + __IO float32 loop_current; // 回路电流 + __IO float32 target_travel; // 目标行程 + __IO float32 actual_travel; // 实际行程 + __IO float32 pressure_s; // 气源压力 + __IO float32 pressure_a; // A路压力 + __IO float32 pressure_b; // B路压力 + __IO float32 friction; // 摩擦力 + __IO float32 elasticity; // 弹簧力 + __IO float32 cpu_percent; // CPU使用率 + __IO float32 cpu_temperature; // CPU温度 + __IO float32 mem_percent; // 内存使用率 + rt_save_param_t save; // 需要保存到FM24的实时参数 +} real_time_data_t; + +/// 驱动使能图标 +typedef union +{ + uint64_t dev; + struct + { + uint64_t hart : 1; // hart模块 + uint64_t bluetooth : 1; // 蓝牙模块 + uint64_t work_mode : 3; // 工作模式 + uint64_t write_protect : 1; // 写保护 + uint64_t lock : 1; // 锁模块 + } Bits; +} driver_icon_enable_u; + +#pragma pack() // 编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式 + +extern device_typedef udevice; ///< 设备参数 +extern __IO calib_param_t calib_param[CALIBPARA_NUM]; ///< 校准参数 +extern real_time_data_t rt_data; ///< 实时参数 +extern mode_params_t mode_params; ///< 模式参数 +extern pid_t _pid; ///< PID参数 +extern driver_icon_enable_u driver_icon_enable; ///< 驱动使能图标 +// 模拟量 +extern __IO uint16_t adc_raw[ADC1_MAX]; ///< ADC原始值 +extern uint32_t mode_default_autoload; ///< 默认自动加载 +// 数字量 +extern __IO float32 pid_target; ///< pid控制目标 +extern __IO float32 pid_actual; ///< pid控制实际 +extern __IO float32 show_loop; ///< 显示电流 +extern __IO float32 show_target; ///< 显示目标 +extern __IO float32 show_actual; ///< 显示实际 +extern __IO float32 range_percentage; ///< 量程百分比 +extern __IO flow_event_e flow_event; ///< 任务流程状态机 +// 函数 +extern void h24_bluetooth_output_dbg(uint8_t *data, uint16_t len); ///< 蓝牙输出调试 +extern void h24_bluetooth_output(uint8_t *data, uint16_t len); ///< 蓝牙输出 +#endif // __ENTITY_H__ diff --git a/User/lib/bootload/bootload.c b/User/lib/bootload/bootload.c new file mode 100644 index 0000000..6dacd43 --- /dev/null +++ b/User/lib/bootload/bootload.c @@ -0,0 +1,229 @@ +#include "bootload.h" +#include "ymodem.h" +#include "sys.h" +#include "delay.h" +#include "cmac.h" +#define AES_CMAC_DIGEST_LENGTH 16 +typedef void (*fnc_ptr)(void); // 用于跳转到应用程序的函数指针 +static bootload_transmit_callback transmit_callback = NULL; +static bootload_end_callback end_callback = NULL; +uint8_t upgrade_key[] = + { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥 + +static AES_CMAC_CTX upgrade_ctx; /**< AES CMAC context for upgrade process */ +static uint8_t pre_upgrade_mic[AES_CMAC_DIGEST_LENGTH]; /**< MIC (Message Integrity Code) before upgrade */ +static uint8_t upgrade_mic[AES_CMAC_DIGEST_LENGTH]; /**< MIC (Message Integrity Code) after upgrade */ +static uint32_t flashdestination = BOOTLOAD_APP_BACKUP_ADDR_START; /**< Flash destination address for bootloading */ +static uint32_t upgrade_size = 0; /**< Size of the upgrade */ +static uint8_t read_cache[LL_FLASH_PAGE_SIZE]; /**< Read cache for flash pages */ +static uint8_t data_src_from; /**< Data source for bootloading */ + +/** + * @brief Perform bootload inspection. + * + * This function calls the `rym_process()` function to perform bootload inspection. + */ +void bootload_inspection(void) +{ + rym_process(); +} + +/** + * @brief Checks if the bootload timeout has occurred. + * + * This function calls the `rym_timeout()` function to determine if the bootload timeout has occurred. + * + * @return TRUE if the bootload timeout has occurred, FALSE otherwise. + */ +BOOL bootload_timeout(void) +{ + return rym_timeout(); +} + +/** + * @brief Handles the beginning of the bootloading process. + * + * This function is responsible for handling the initial steps of the bootloading process. + * It checks if the length of the data to be bootloaded is greater than the end address of the application area. + * If the length is greater, it returns an error code indicating that the bootloading cannot proceed. + * Otherwise, it sets the flash destination address to the start address of the backup area, + * erases the bank of the flash memory where the application is stored, + * and initializes the AES-CMAC context for the upgrade process. + * + * @param p Pointer to the data to be bootloaded. + * @param len Length of the data to be bootloaded. + * @return Error code indicating the result of the operation. + * - RYM_CODE_CAN: If the length of the data is greater than the end address of the application area. + * - RYM_CODE_NONE: If the operation is successful. + */ +static rym_code_e on_begin(uint8_t *p, uint32_t len) +{ + if (len > BOOTLOAD_APP_END_ADDRESS) + { + return RYM_CODE_CAN; + } + + flashdestination = BOOTLOAD_APP_BACKUP_ADDR_START; + LL_FLASH_Unlock(FLASH); + LL_FLASH_EraseBank(LL_FLASH_BANK2); + LL_FLASH_Lock(FLASH); + + AES_CMAC_Init(&upgrade_ctx); + AES_CMAC_SetKey(&upgrade_ctx, upgrade_key); + return RYM_CODE_NONE; +} + +/** + * @brief Handles the received data and programs it into the flash memory. + * + * This function unlocks the flash memory, programs the received data into the specified flash destination, + * locks the flash memory again, updates the AES-CMAC context with the received data, and increments the flash destination. + * + * @param p Pointer to the data buffer. + * @param len Length of the data buffer. + * @return The result code indicating the success or failure of the operation. + */ +static rym_code_e on_data(uint8_t *p, uint32_t len) +{ + LL_FLASH_Unlock(FLASH); + LL_FLASH_Program(flashdestination, p, len); + LL_FLASH_Lock(FLASH); + AES_CMAC_Update(&upgrade_ctx, p, len); + flashdestination += len; + return RYM_CODE_NONE; +} + +/** + * @brief Calculate the MIC (Message Integrity Code) for the firmware upgrade. + * + * This function calculates the MIC using AES-CMAC algorithm for the firmware upgrade data. + * It reads the firmware data from flash memory in pages and updates the MIC calculation. + * Finally, it compares the calculated MIC with the pre-upgrade MIC to determine the success of the upgrade. + * + * @param p Pointer to the firmware data. + * @param len Length of the firmware data. + * @return The result code indicating the success or failure of the upgrade process. + */ +static rym_code_e on_end(uint8_t *p, uint32_t len) +{ + AES_CMAC_Final(pre_upgrade_mic, &upgrade_ctx); + upgrade_size = flashdestination - BOOTLOAD_APP_BACKUP_ADDR_START; + + AES_CMAC_Init(&upgrade_ctx); + AES_CMAC_SetKey(&upgrade_ctx, upgrade_key); + uint32_t start = BOOTLOAD_APP_BACKUP_ADDR_START; + uint16_t num = (upgrade_size / LL_FLASH_PAGE_SIZE); + uint16_t remain = (upgrade_size % LL_FLASH_PAGE_SIZE); + + // STM32L476RG的flash页大小为2K,先读取整数页,再读取余数 + for (uint16_t i = 0; i < num; i++) + { + LL_FLASH_Read((start + i * (LL_FLASH_PAGE_SIZE)), read_cache, LL_FLASH_PAGE_SIZE); + AES_CMAC_Update(&upgrade_ctx, read_cache, LL_FLASH_PAGE_SIZE); + } + + if (remain) + { + osel_memset(read_cache, 0, LL_FLASH_PAGE_SIZE); + LL_FLASH_Read((start + num * (LL_FLASH_PAGE_SIZE)), read_cache, remain); + AES_CMAC_Update(&upgrade_ctx, read_cache, remain); + } + + AES_CMAC_Final(upgrade_mic, &upgrade_ctx); + + // 比较mic,相同可以写入标志位告知应用程序升级成功 + if (osel_memcmp(upgrade_mic, pre_upgrade_mic, AES_CMAC_DIGEST_LENGTH) == 0) + { + end_callback(TRUE); + } + else + { + end_callback(FALSE); + } + return RYM_CODE_NONE; +} + +/** + * @brief Handles the transmission of data. + * + * This function calls the transmit_callback function to transmit the data from the specified source. + * + * @param p Pointer to the data buffer. + * @param len Length of the data buffer. + * @return The return code indicating the status of the transmission. + */ +static rym_code_e on_transmit(uint8_t *p, uint32_t len) +{ + transmit_callback(data_src_from, p, (uint16_t)len); + return RYM_CODE_NONE; +} + +/** + * @brief Initializes the bootload module. + * + * This function initializes the bootload module by setting the transmit callback + * and configuring the RYM module. It asserts if the initialization fails. + * + * @param transmit The transmit callback function. + */ +void bootload_init(bootload_transmit_callback transmit, bootload_end_callback end) +{ + BOOL res = FALSE; + + transmit_callback = transmit; + end_callback = end; + + res = rym_init(); + DBG_ASSERT(res == TRUE __DBG_LINE); + + res = rym_config(on_begin, on_data, on_end, on_transmit, BOOTLOAD_TIMEOUT); + DBG_ASSERT(res == TRUE __DBG_LINE); +} + +/** + * @brief Sets the data source index for bootload transmission. + * + * This function sets the data source index for bootload transmission. The data source index + * determines the starting point from which the data will be transmitted. + * + * @param to_index The index of the data source. + */ +void bootload_transmit_from(const uint8_t to_index) +{ + data_src_from = to_index; +} + +/** + * @brief Jump to the specified address and execute the bootloader. + * + * @param address The entry address of the bootloader. + */ +void bootload_jump(uint32_t address) +{ + // Get the entry address of the application program + fnc_ptr jump_to_bootload; + jump_to_bootload = (fnc_ptr)(*(__IO uint32_t *)(address + 4)); + + // Disable RCC + RCC->APB1ENR1 = 0; + RCC->APB1ENR2 = 0; + RCC->APB2ENR = 0; + RCC->AHB1ENR = 0; + RCC->AHB2ENR = 0; + RCC->AHB3ENR = 0; + + // Disable SysTick + SysTick->CTRL = 0; + // 清空SysTick + SysTick->LOAD = 0; + // 清空SysTick + SysTick->VAL = 0; + // 设置向量表偏移地址 + SCB->VTOR = address; + // 设置堆栈指针 + sys_msr_msp(*(__IO uint32_t *)address); + // 跳转 + jump_to_bootload(); +} diff --git a/User/lib/bootload/bootload.h b/User/lib/bootload/bootload.h new file mode 100644 index 0000000..44dbfaa --- /dev/null +++ b/User/lib/bootload/bootload.h @@ -0,0 +1,100 @@ +#ifndef __BOOTLOAD_H +#define __BOOTLOAD_H +#include "lib.h" +#include "flash.h" +#include "flow.h" + +/** + * @brief Defines the start address of the application in flash memory. + */ +#define BOOTLOAD_APP_START_ADDRESS ((uint32_t)0x08000000u) + +/** + * @brief Defines the end address of the application in flash memory. + */ +#define BOOTLOAD_APP_END_ADDRESS (BOOTLOAD_APP_START_ADDRESS + 220 * LL_FLASH_PAGE_SIZE) // 220*2048 = 450560 + +/** + * @brief Defines the start address of the bootloader in flash memory. + */ +#define BOOTLOAD_START_ADDRESS BOOTLOAD_APP_END_ADDRESS + +/** + * @brief Defines the start address of the backup area for the application in flash memory. + */ +#define BOOTLOAD_APP_BACKUP_ADDR_START (BOOTLOAD_APP_START_ADDRESS + LL_FLASH_BANK1_PAGE_NUM * LL_FLASH_PAGE_SIZE) + +/** + * @brief Defines the timeout for the bootloading process. + * + * This macro defines the timeout for the bootloading process, in seconds. The default value is 10 seconds. + */ +#define BOOTLOAD_TIMEOUT 10 + +/** + * @brief A function pointer type for a bootload transmit callback function. + * + * This function pointer type is used for a bootload transmit callback function, which is + * called when data needs to be transmitted to the bootloader. The function is passed the + * source of the data (the index of the data packet), a pointer to the data buffer, and the + * length of the data buffer. + * + * @param data_src The index of the data packet that is being transmitted. + * @param buf A pointer to the data buffer. + * @param len The length of the data buffer. + */ +typedef void (*bootload_transmit_callback)(const uint8_t data_src, const uint8_t *buf, const uint16_t len); + +/** + * @brief A function pointer type for a bootload end callback function. + * + * This function pointer type is used for a bootload end callback function, which is called + * when the bootloading process is complete. The function takes no parameters and returns no + * value. + */ +typedef void (*bootload_end_callback)(BOOL); + +/** + * @brief initializes the bootloader + * + * This function initializes the bootloader, including setting up the communication + * with the host and configuring the flash memory for bootloading. + * + * @param transmit a pointer to the function that will be called to transmit data to the host + */ +void bootload_init(bootload_transmit_callback transmit, bootload_end_callback end); + +/** + * @brief Transmits data from the specified index. + * + * This function transmits data from the specified index to the bootloader. + * + * @param to_index The index from which the data should be transmitted. + */ +void bootload_transmit_from(const uint8_t to_index); + +/** + * @brief Jumps to the specified address. + * + * This function jumps to the specified address, which is typically the start address of the bootloader. + * + * @param address The address to jump to. + */ +void bootload_jump(uint32_t address); + +/** + * @brief Performs inspection of the bootloader. + * + * This function performs inspection of the bootloader, such as checking the version or integrity of the bootloader. + */ +void bootload_inspection(void); + +/** + * @brief Checks if a timeout has occurred. + * + * This function checks if a timeout has occurred during the bootloading process. + * + * @return TRUE if a timeout has occurred, FALSE otherwise. + */ +BOOL bootload_timeout(void); +#endif // __BOOTLOAD_H diff --git a/User/lib/bootload/readme.md b/User/lib/bootload/readme.md new file mode 100644 index 0000000..d0231d7 --- /dev/null +++ b/User/lib/bootload/readme.md @@ -0,0 +1,50 @@ + +# BOOTLOADER介绍 + + +STM32的BOOTLOADER是在芯片复位或从停机模式唤醒时执行的一段小程序,它负责将用户代码加载到内存中并启动它。STM32F1、F4、H7等不同系列的MCU可能会有不同的BOOTLOADER程序。 + +BOOTLOADER通常用于以下几种情况: + +1. 在应用程序无法正常启动时,提供一个后备启动方式。 +2. 在系统需要进行固件更新时,可以先通过BOOTLOADER加载新的用户代码。 +3. 用于在线调试或调试无法通过JTAG/SWD接口访问时,可以通过BOOTLOADER加载调试工具。 + +BOOTLOADER的设计和实现通常依赖于芯片的内部结构和特性,以及用户代码存储的介质(如内部FLASH,外部SPI FLASH等)。 + +一个简单的BOOTLOADER示例可能包括以下步骤: + +1. 复位后,芯片开始执行内部的BOOTLOADER程序。 +2. 通过某种通信接口(如USART,I2C,SPI)接收新的用户程序代码。 +3. 将接收到的代码写入用户代码存储区(如内部FLASH)。 +4. 设置启动引脚或者配置BOOT引导模式寄存器,选择启动用户代码。 +5. 重启芯片,这次不再执行BOOTLOADER,而是加载并运行新的用户程序代码。 + +注意:实际的BOOTLOADER实现可能会更加复杂,包括错误检查和处理、加密解密、固件完整性校验等安全措施。 + +# bootload.c 文件说明 + +`bootload.c`是一个实现引导加载程序(bootloader)功能的源代码文件。引导加载程序是一段在系统启动时运行的代码,负责初始化硬件设备、建立内存空间映射图,然后加载操作系统内核并将控制权转交给它。 + +以下是 `bootload.c`文件中可能包含的主要函数和其功能: + +1. **系统启动函数** :这个函数是引导加载程序的入口点,它负责启动整个引导加载过程。 +2. **硬件初始化函数** :这些函数负责初始化系统的硬件设备,包括CPU、内存、IO设备等。 +3. **内存映射设置函数** :这些函数负责建立内存空间的映射图,包括物理内存、虚拟内存的映射关系。 +4. **操作系统内核加载函数** :这些函数负责加载操作系统内核,包括从存储设备读取内核镜像,加载到内存中,然后跳转到内核的入口点。 +5. **错误处理函数** :这些函数负责处理在引导加载过程中可能出现的各种错误,包括硬件错误、内核加载错误等。 + + + +# ymodem.c 文件说明 + +`ymodem.c`是一个实现YMODEM协议的源代码文件。YMODEM是一种用于文件传输的协议,它在XMODEM协议的基础上增加了一些新的特性,例如支持更大的文件和文件名传输。 + +以下是 `ymodem.c`文件中可能包含的主要函数和其功能: + +1. **初始化和结束传输的函数** :这些函数负责设置传输的开始和结束,包括打开和关闭必要的硬件接口,设置传输参数等。 +2. **发送和接收数据包的函数** :这些函数负责实际的数据传输,包括将数据打包成YMODEM格式的数据包,通过硬件接口发送和接收数据包,处理数据包的确认和重传等。 +3. **CRC校验的函数** :这些函数负责计算和检查数据包的CRC(循环冗余校验)值,以确保数据的完整性。 +4. **处理错误和重试的函数** :这些函数负责处理在传输过程中可能出现的各种错误,包括数据包丢失、CRC校验失败等,并在必要时进行重试。 + +此外,`ymodem.c`文件还可能包含一些辅助函数,用于处理如超时、缓冲区管理等问题。 diff --git a/User/lib/bootload/test_ymodem.c b/User/lib/bootload/test_ymodem.c new file mode 100644 index 0000000..d7c6b08 --- /dev/null +++ b/User/lib/bootload/test_ymodem.c @@ -0,0 +1,79 @@ +#include "unity.h" +#include "ymodem.c" + +void setUp(void) +{ + // 这里可以进行每个测试用例开始前的设置 +} + +void tearDown(void) +{ + // 这里可以进行每个测试用例结束后的清理 +} + +void test_CRC16(void) +{ + unsigned char data[] = {0x01, 0x02, 0x03, 0x04, 0x05}; + TEST_ASSERT_EQUAL_HEX16(EXPECTED_CRC_VALUE, CRC16(data, sizeof(data))); +} + +void test_IS_CAP_LETTER(void) +{ + TEST_ASSERT_TRUE(IS_CAP_LETTER('A')); + TEST_ASSERT_FALSE(IS_CAP_LETTER('a')); +} + +void test_IS_LC_LETTER(void) +{ + TEST_ASSERT_TRUE(IS_LC_LETTER('a')); + TEST_ASSERT_FALSE(IS_LC_LETTER('A')); +} + +void test_IS_09(void) +{ + TEST_ASSERT_TRUE(IS_09('0')); + TEST_ASSERT_FALSE(IS_09('A')); +} + +void test_ISVALIDHEX(void) +{ + TEST_ASSERT_TRUE(ISVALIDHEX('A')); + TEST_ASSERT_TRUE(ISVALIDHEX('a')); + TEST_ASSERT_TRUE(ISVALIDHEX('0')); + TEST_ASSERT_FALSE(ISVALIDHEX('G')); +} + +void test_ISVALIDDEC(void) +{ + TEST_ASSERT_TRUE(ISVALIDDEC('0')); + TEST_ASSERT_FALSE(ISVALIDDEC('A')); +} + +void test_CONVERTDEC(void) +{ + TEST_ASSERT_EQUAL_HEX8(0, CONVERTDEC('0')); + TEST_ASSERT_EQUAL_HEX8(9, CONVERTDEC('9')); +} + +void test_CONVERTHEX(void) +{ + TEST_ASSERT_EQUAL_HEX8(10, CONVERTHEX('A')); + TEST_ASSERT_EQUAL_HEX8(10, CONVERTHEX('a')); + TEST_ASSERT_EQUAL_HEX8(0, CONVERTHEX('0')); +} + +int main(void) +{ + UNITY_BEGIN(); + + RUN_TEST(test_CRC16); + RUN_TEST(test_IS_CAP_LETTER); + RUN_TEST(test_IS_LC_LETTER); + RUN_TEST(test_IS_09); + RUN_TEST(test_ISVALIDHEX); + RUN_TEST(test_ISVALIDDEC); + RUN_TEST(test_CONVERTDEC); + RUN_TEST(test_CONVERTHEX); + + return UNITY_END(); +} diff --git a/User/lib/bootload/ymodem.c b/User/lib/bootload/ymodem.c new file mode 100644 index 0000000..8bafe13 --- /dev/null +++ b/User/lib/bootload/ymodem.c @@ -0,0 +1,633 @@ +/** + * @file ymodem.c + * @author xxx + * @date 2024-02-18 19:32:40 + * @brief + * 该模块实现了YMODEM协议的核心功能,包括初始化、配置、数据接收、握手、数据传输和结束处理。 + * 它使用了回调函数来处理不同阶段的事件,并使用信号量来同步不同的流程。CRC校验是用来确保数据传输的完整性和准确性 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#include "ymodem.h" +#include "sys.h" +#include "delay.h" +#include "flow.h" + +sqqueue_ctrl_t rym_sqqueue; // 一个接收队列控制结构体,用于管理接收到的数据。 +static uint32_t tm_sec = 0; // 握手超时时间,用于握手阶段的超时计时 +static enum rym_stage stage = RYM_STAGE_NONE; // 当前的阶段 +static int32_t rym_tm_sec = 0; // YMODEM超时计时器 + +static uint8_t aPacketData[_RYM_PKG_SZ]; // 数据包缓冲区 + +// 回调函数,用于处理不同阶段的事件 +static rym_callback rym_on_begin = NULL; +static rym_callback rym_on_data = NULL; +static rym_callback rym_on_end = NULL; +static rym_callback rym_transmit = NULL; + +static struct flow handshake_fw; // 握手流程 +static struct flow trans_fw; // 传输流程 +static struct flow finsh_fw; // 结束流程 +static struct flow_sem msg_sem; // 消息信号量,用于同步 + +static const uint16_t ccitt_table[256] = + { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}; + +uint16_t CRC16(unsigned char *q, int len) +{ + uint16_t crc = 0; + + while (len-- > 0) + crc = (crc << 8) ^ ccitt_table[((crc >> 8) ^ *q++) & 0xff]; + return crc; +} + +/* Exported macro ------------------------------------------------------------*/ +#define IS_CAP_LETTER(c) (((c) >= 'A') && ((c) <= 'F')) +#define IS_LC_LETTER(c) (((c) >= 'a') && ((c) <= 'f')) +#define IS_09(c) (((c) >= '0') && ((c) <= '9')) +#define ISVALIDHEX(c) (IS_CAP_LETTER(c) || IS_LC_LETTER(c) || IS_09(c)) +#define ISVALIDDEC(c) IS_09(c) +#define CONVERTDEC(c) (c - '0') + +#define CONVERTHEX_ALPHA(c) (IS_CAP_LETTER(c) ? ((c) - 'A' + 10) : ((c) - 'a' + 10)) +#define CONVERTHEX(c) (IS_09(c) ? ((c) - '0') : CONVERTHEX_ALPHA(c)) +/** + * @brief Convert a string to an integer + * @param p_inputstr: The string to be converted + * @param p_intnum: The integer value + * @retval 1: Correct + * 0: Error + */ +uint32_t Str2Int(uint8_t *p_inputstr, uint32_t *p_intnum) +{ + uint32_t i = 0, res = 0; + uint32_t val = 0; + + if ((p_inputstr[0] == '0') && ((p_inputstr[1] == 'x') || (p_inputstr[1] == 'X'))) + { + i = 2; + while ((i < 11) && (p_inputstr[i] != '\0')) + { + if (ISVALIDHEX(p_inputstr[i])) + { + val = (val << 4) + CONVERTHEX(p_inputstr[i]); + } + else + { + /* Return 0, Invalid input */ + res = 0; + break; + } + i++; + } + + /* valid result */ + if (p_inputstr[i] == '\0') + { + *p_intnum = val; + res = 1; + } + } + else /* max 10-digit decimal input */ + { + while ((i < 11) && (res != 1)) + { + if (p_inputstr[i] == '\0') + { + *p_intnum = val; + /* return 1 */ + res = 1; + } + else if (((p_inputstr[i] == 'k') || (p_inputstr[i] == 'K')) && (i > 0)) + { + val = val << 10; + *p_intnum = val; + res = 1; + } + else if (((p_inputstr[i] == 'm') || (p_inputstr[i] == 'M')) && (i > 0)) + { + val = val << 20; + *p_intnum = val; + res = 1; + } + else if (ISVALIDDEC(p_inputstr[i])) + { + val = val * 10 + CONVERTDEC(p_inputstr[i]); + } + else + { + /* return 0, Invalid input */ + res = 0; + break; + } + i++; + } + } + + return res; +} + +/** + * @brief Read data from the circular queue. + * + * This function reads the specified length of data from the circular queue and stores it in the given buffer. + * If the length of data in the queue is greater than or equal to the specified length, it directly reads the specified length of data. + * If the length of data in the queue is less than the specified length, it reads all the data in the queue. + * + * @param buffer The buffer to store the data. + * @param len The length of data to read. + * + * @return The actual length of data read. + */ +static uint16_t rym_sqqueue_read(void *buffer, uint16_t len) +{ + uint16_t i = 0; + uint8_t *buf = buffer; + if (rym_sqqueue.get_len(&rym_sqqueue) >= len) + { + for (i = 0; i < len; i++) + { + buf[i] = *((uint8_t *)rym_sqqueue.del(&rym_sqqueue)); + } + } + else + { + while ((rym_sqqueue.get_len(&rym_sqqueue) != 0) && (i < len)) + { + buf[i] = *((uint8_t *)rym_sqqueue.del(&rym_sqqueue)); + } + } + + return i; +} + +/** + * @brief Initializes the parameters for the YMODEM process. + * + * This function sets the stage variable to the specified stage and initializes the rym_tm_sec variable with the value of tm_sec. + * If the stage is RYM_STAGE_ESTABLISHING, it also clears the rym_sqqueue. + * + * @param st The stage of the YMODEM process. + */ +static void rym_process_params_init(enum rym_stage st) +{ + stage = st; + rym_tm_sec = tm_sec; + if (st == RYM_STAGE_ESTABLISHING) + { + rym_sqqueue.clear_sqq(&rym_sqqueue); + } +} + +/** + * @brief Performs the handshake process for the YMODEM protocol. + * + * This function reads packets from the input queue and performs the necessary checks and actions + * to establish a connection and initiate file transfer using the YMODEM protocol. + * + * @param fl The flow structure containing the necessary variables and synchronization mechanisms. + * @return The result of the handshake process. + * - 0: Handshake process completed successfully. + * - Non-zero: Handshake process failed. + */ +static uint8_t rym_do_handshake_process(struct flow *fl) +{ + uint8_t index = 0; + FL_HEAD(fl); + static uint16_t rym_recv_len = 0; + static uint16_t recv_crc, cal_crc; + static uint8_t *file_ptr = NULL; + static uint8_t file_name[FILE_NAME_LENGTH]; + static uint8_t file_size[FILE_SIZE_LENGTH]; + static uint32_t filesize; + for (;;) + { + FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC); + if (FL_SEM_IS_RELEASE(fl, &msg_sem)) + { + rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1); + if (rym_recv_len == 1) + { + if (aPacketData[PACKET_START_INDEX] != RYM_CODE_SOH && aPacketData[PACKET_START_INDEX] != RYM_CODE_STX) + continue; + + /* SOH/STX + seq + payload + crc */ + rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_NUMBER_INDEX], + _RYM_PKG_SZ - 1); + if (rym_recv_len != (_RYM_PKG_SZ - 1)) + continue; + /* sanity check */ + if ((aPacketData[PACKET_NUMBER_INDEX] != 0) || (aPacketData[PACKET_CNUMBER_INDEX] != 0xFF)) + continue; + recv_crc = (uint16_t)(*(&aPacketData[PACKET_START_INDEX] + _RYM_PKG_SZ - 2) << 8) | + *(&aPacketData[PACKET_START_INDEX] + _RYM_PKG_SZ - 1); + cal_crc = CRC16(aPacketData + PACKET_DATA_INDEX, _RYM_PKG_SZ - 5); + if (recv_crc != cal_crc) + continue; + + if (rym_on_begin != NULL) + { + file_ptr = aPacketData + PACKET_DATA_INDEX; + while ((*file_ptr != 0) && (index < FILE_NAME_LENGTH)) + { + file_name[index++] = *file_ptr++; + } + file_name[index++] = '\0'; + index = 0; + file_ptr++; + while ((*file_ptr != ' ') && (index < FILE_SIZE_LENGTH)) + { + file_size[index++] = *file_ptr++; + } + file_size[index++] = '\0'; + Str2Int(file_size, &filesize); + + if (RYM_CODE_NONE != rym_on_begin(file_name, filesize)) + { + for (uint8_t i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++) + { + aPacketData[0] = RYM_CODE_CAN; + rym_transmit(aPacketData, 1); + } + } + else + { + aPacketData[0] = RYM_CODE_ACK; + rym_transmit(aPacketData, 1); + FL_LOCK_DELAY(fl, FL_CLOCK_100MSEC * 5); + aPacketData[0] = RYM_CODE_C; + rym_transmit(aPacketData, 1); + rym_process_params_init(RYM_STAGE_TRANSMITTING); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + } + } + } + } + else + { + aPacketData[0] = RYM_CODE_C; + rym_transmit(aPacketData, 1); + rym_tm_sec--; + } + } + FL_TAIL(fl); +} + +/** + * @brief Transfers data using the YMODEM protocol. + * + * This function is responsible for transferring data using the YMODEM protocol. + * It receives the size of the data to be transferred and a pointer to the code + * that will be returned. It performs various checks on the received data and + * calculates the CRC to ensure data integrity. If all checks pass, it sets the + * code to RYM_CODE_ACK and returns 0. Otherwise, it returns an error code. + * + * @param data_size The size of the data to be transferred. + * @param code Pointer to the code that will be returned. + * @return 0 if successful, otherwise an error code. + */ +static int8_t rym_tran_data(uint16_t data_size, uint8_t *code) +{ + DBG_ASSERT(NULL != code __DBG_LINE); + uint16_t recv_len = 0; + uint16_t recv_crc, cal_crc; + const uint16_t tran_size = PACKET_HEADER_SIZE - 1 + data_size + PACKET_TRAILER_SIZE; + + /* seq + data + crc */ + recv_len = rym_sqqueue_read(&aPacketData[PACKET_NUMBER_INDEX], + tran_size); + if (recv_len != tran_size) + return -RYM_ERR_DSZ; + /* sanity check */ + if ((aPacketData[PACKET_NUMBER_INDEX] + aPacketData[PACKET_CNUMBER_INDEX]) != 0xFF) + return -RYM_ERR_SEQ; + /* As we are sending C continuously, there is a chance that the + * sender(remote) receive an C after sending the first handshake package. + * So the sender will interpret it as NAK and re-send the package. So we + * just ignore it and proceed. */ + if (stage == RYM_STAGE_ESTABLISHED && aPacketData[PACKET_NUMBER_INDEX] == RYM_CODE_NONE) + { + *code = RYM_CODE_NONE; + return 0; + } + + stage = RYM_STAGE_TRANSMITTING; + + recv_crc = (uint16_t)(*(&aPacketData[PACKET_START_INDEX] + tran_size - 1) << 8) | + *(&aPacketData[PACKET_START_INDEX] + tran_size); + cal_crc = CRC16(aPacketData + PACKET_DATA_INDEX, data_size); + if (recv_crc != cal_crc) + return -RYM_ERR_CRC; + + *code = RYM_CODE_ACK; + return 0; +} + +/** + * @brief Performs the YMODEM transmission process. + * + * This function is responsible for handling the YMODEM transmission process. + * It receives packets of data and performs the necessary operations based on the received data. + * It handles timeouts and retransmissions if necessary. + * + * @param fl The flow structure pointer. + * @return The status of the transmission process. + */ +static uint8_t rym_do_trans_process(struct flow *fl) +{ + FL_HEAD(fl); + static uint16_t data_size, rym_recv_len; + static uint8_t rym_code; + static uint16_t tran_timeout = 0; + for (;;) + { + FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC); + if (FALSE == FL_SEM_IS_RELEASE(fl, &msg_sem)) + { + if (tran_timeout++ >= 5) + { + tran_timeout = 0; + rym_process_params_init(RYM_STAGE_ESTABLISHING); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + } + } + else + { + tran_timeout = 0; + rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1); + if (rym_recv_len == 1) + { + if (aPacketData[PACKET_START_INDEX] == RYM_CODE_SOH) + data_size = PACKET_SIZE; + else if (aPacketData[PACKET_START_INDEX] == RYM_CODE_STX) + data_size = PACKET_1K_SIZE; + else if (aPacketData[PACKET_START_INDEX] == RYM_CODE_EOT) + { + aPacketData[0] = RYM_CODE_NAK; + rym_transmit(aPacketData, 1); + rym_process_params_init(RYM_STAGE_FINISHING); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + continue; + } + else + { + rym_process_params_init(RYM_STAGE_ESTABLISHING); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + continue; + } + + if (rym_tran_data(data_size, &rym_code) == 0) + { + if (rym_on_data != NULL) + rym_on_data(aPacketData + PACKET_DATA_INDEX, data_size); + + if (rym_code == RYM_CODE_CAN) + { + for (uint8_t i = 0; i < RYM_END_SESSION_SEND_CAN_NUM; i++) + { + aPacketData[0] = RYM_CODE_CAN; + rym_transmit(aPacketData, 1); + } + } + else if (rym_code == RYM_CODE_ACK) + { + aPacketData[0] = RYM_CODE_ACK; + rym_transmit(aPacketData, 1); + } + } + } + } + } + FL_TAIL(fl); +} + +/** + * @brief Performs the finishing process for the YMODEM protocol. + * + * This function is responsible for handling the final stage of the YMODEM protocol, + * where the receiver receives the end of transmission (EOT) signal from the sender. + * It verifies the received EOT signal, sends an acknowledgement (ACK) signal back to + * the sender, and waits for the start of header (SOH) signal to receive the final + * packet containing the payload and checksum. If the received packet is valid, it + * calculates the checksum and compares it with the received checksum. If they match, + * it sets the stage to RYM_STAGE_FINISHED and invokes the callback function if + * available. This function also handles timeout conditions and reinitializes the + * protocol parameters if necessary. + * + * @param fl The flow structure pointer. + * @return The result of the finishing process. + */ +static uint8_t rym_do_finish_process(struct flow *fl) +{ + FL_HEAD(fl); + static uint16_t rym_recv_len; + static uint16_t recv_crc, cal_crc; + static uint16_t tran_timeout = 0; + + for (;;) + { + FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC); + if (FALSE == FL_SEM_IS_RELEASE(fl, &msg_sem)) + { + if (tran_timeout++ >= 5) + { + tran_timeout = 0; + rym_process_params_init(RYM_STAGE_ESTABLISHING); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC); + } + } + else + { + tran_timeout = 0; + /* read the length of the packet */ + rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1); + if (rym_recv_len == 1) + { + if (aPacketData[PACKET_START_INDEX] != RYM_CODE_EOT) + continue; + + /* send an ACK */ + aPacketData[0] = RYM_CODE_ACK; + rym_transmit(aPacketData, 1); + FL_LOCK_DELAY(fl, FL_CLOCK_100MSEC * 5); + /* send a C */ + aPacketData[0] = RYM_CODE_C; + rym_transmit(aPacketData, 1); + + FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, &msg_sem, FL_CLOCK_SEC); + if (FALSE == FL_SEM_IS_RELEASE(fl, &msg_sem)) + continue; + /* read the length of the packet */ + rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_START_INDEX], 1); + if (rym_recv_len == 1) + { + if (aPacketData[PACKET_START_INDEX] != RYM_CODE_SOH) + continue; + + /* SOH/STX + seq + payload + crc */ + rym_recv_len = rym_sqqueue_read(&aPacketData[PACKET_NUMBER_INDEX], + _RYM_SOH_PKG_SZ - 1); + if (rym_recv_len != (_RYM_SOH_PKG_SZ - 1)) + continue; + /* sanity check */ + if ((aPacketData[PACKET_NUMBER_INDEX] != 0) || (aPacketData[PACKET_CNUMBER_INDEX] != 0xFF)) + continue; + recv_crc = (uint16_t)(*(&aPacketData[PACKET_START_INDEX] + _RYM_SOH_PKG_SZ - 2) << 8) | + *(&aPacketData[PACKET_START_INDEX] + _RYM_SOH_PKG_SZ - 1); + cal_crc = CRC16(aPacketData + PACKET_DATA_INDEX, _RYM_SOH_PKG_SZ - 5); + if (recv_crc != cal_crc) + continue; + + /* we got a valid packet. invoke the callback if there is one. */ + stage = RYM_STAGE_FINISHED; + aPacketData[0] = RYM_CODE_ACK; + rym_transmit(aPacketData, 1); + /* we already got one EOT in the caller. invoke the callback if there is + * one. */ + if (rym_on_end) + rym_on_end(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE); + } + } + } + } + FL_TAIL(fl); +} + +/** + * @brief Process the Ymodem protocol stages. + * + * This function is responsible for handling the different stages of the Ymodem protocol. + * It performs the necessary actions based on the current stage. + * + * @note The stages include establishing connection, transmitting data, finishing, and others. + * + * @param None + * @return None + */ +void rym_process(void) +{ + switch (stage) + { + case RYM_STAGE_ESTABLISHING: // 建立连接 (Establishing connection) + rym_do_handshake_process(&handshake_fw); + break; + case RYM_STAGE_TRANSMITTING: // 传输中 (Transmitting) + rym_do_trans_process(&trans_fw); + break; + case RYM_STAGE_FINISHING: // 结束 (Finishing) + rym_do_finish_process(&finsh_fw); + break; + case RYM_STAGE_NONE: + rym_process_params_init(RYM_STAGE_ESTABLISHING); + break; + case RYM_STAGE_FINISHED: + rym_tm_sec = 0; + break; + default: + // rym_process_params_init(RYM_STAGE_ESTABLISHING); + break; + } +} + +/** + * @brief Checks if the YMODEM receive timeout has occurred. + * @return TRUE if the timeout has occurred, FALSE otherwise. + */ +BOOL rym_timeout(void) +{ + return rym_tm_sec == 0; +} + +/** + * @brief Initializes the YMODEM protocol for receiving files. + * + * This function initializes the necessary data structures and variables + * for receiving files using the YMODEM protocol. + * + * @return TRUE if initialization is successful, FALSE otherwise. + */ +BOOL rym_init(void) +{ + sqqueue_ctrl_init(&rym_sqqueue, sizeof(uint8_t), _RYM_PKG_SZ); + FL_INIT(&handshake_fw); + FL_INIT(&trans_fw); + FL_INIT(&finsh_fw); + return TRUE; +} + +/** + * @brief Receive data using the Ymodem protocol. + * + * This function is used to receive data transmitted using the Ymodem protocol and store it in the specified buffer. + * + * @param p Pointer to the data storage buffer. + */ +uint16_t rym_receive(void *p, uint16_t size) +{ + rym_sqqueue.string_enter(&rym_sqqueue, p, size); + FLOW_SEM_RELEASE(&msg_sem); + return 0; +} + +/** + * @brief Configures the YMODEM protocol with the specified callbacks and handshake timeout. + * + * This function sets the callback functions for the YMODEM protocol, which will be called during different stages of the protocol. + * The `on_begin` callback is called when the YMODEM transfer begins. + * The `on_data` callback is called when a data packet is received during the transfer. + * The `on_end` callback is called when the YMODEM transfer ends. + * The `on_transmit` callback is called when a data packet needs to be transmitted during the transfer. + * The `handshake_timeout` parameter specifies the timeout duration for the handshake phase of the YMODEM protocol. + * + * @param on_begin The callback function to be called when the YMODEM transfer begins. + * @param on_data The callback function to be called when a data packet is received during the transfer. + * @param on_end The callback function to be called when the YMODEM transfer ends. + * @param on_transmit The callback function to be called when a data packet needs to be transmitted during the transfer. + * @param handshake_timeout The timeout duration for the handshake phase of the YMODEM protocol. + * + * @return TRUE if the configuration was successful, FALSE otherwise. + */ +BOOL rym_config(rym_callback on_begin, rym_callback on_data, + rym_callback on_end, rym_callback on_transmit, + int handshake_timeout) +{ + rym_on_begin = on_begin; + rym_on_data = on_data; + rym_on_end = on_end; + rym_transmit = on_transmit; + tm_sec = handshake_timeout; + return TRUE; +} diff --git a/User/lib/bootload/ymodem.h b/User/lib/bootload/ymodem.h new file mode 100644 index 0000000..e6ce0f1 --- /dev/null +++ b/User/lib/bootload/ymodem.h @@ -0,0 +1,180 @@ +/** + * @file ymodem.h + * @author xsh + * @date 2024-02-18 19:32:46 + * @brief + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __YMODEM_H__ +#define __YMODEM_H__ + +#include "lib.h" + +enum rym_code +{ + RYM_CODE_NONE = 0x00, + RYM_CODE_SOH = 0x01, /* start of 128-byte data packet */ + RYM_CODE_STX = 0x02, /* start of 1024-byte data packet */ + RYM_CODE_EOT = 0x04, /* end of transmission */ + RYM_CODE_ACK = 0x06, /* acknowledge */ + RYM_CODE_NAK = 0x15, /* negative acknowledge */ + RYM_CODE_CAN = 0x18, /* two of these in succession aborts transfer */ + RYM_CODE_C = 0x43, /* 'C' == 0x43, request 16-bit CRC */ +}; +typedef enum rym_code rym_code_e; + +/* RYM error code + * + * We use the rt_err_t to return error values. We take use of current error + * codes available in RTT and append ourselves. + */ +/* timeout on handshake */ +#define RYM_ERR_TMO 0x70 +/* wrong code, wrong SOH, STX etc. */ +#define RYM_ERR_CODE 0x71 +/* wrong sequence number */ +#define RYM_ERR_SEQ 0x72 +/* wrong CRC checksum */ +#define RYM_ERR_CRC 0x73 +/* not enough data received */ +#define RYM_ERR_DSZ 0x74 +/* the transmission is aborted by user */ +#define RYM_ERR_CAN 0x75 + +/* how many ticks wait for chars between packet. */ +#ifndef RYM_WAIT_CHR_TICK +#define RYM_WAIT_CHR_TICK (OSEL_TICK_RATE_HZ * 3) +#endif +/* how many ticks wait for between packet. */ +#ifndef RYM_WAIT_PKG_TICK +#define RYM_WAIT_PKG_TICK (OSEL_TICK_RATE_HZ * 3) +#endif +/* how many ticks between two handshake code. */ +#ifndef RYM_CHD_INTV_TICK +#define RYM_CHD_INTV_TICK (OSEL_TICK_RATE_HZ * 3) +#endif + +/* how many CAN be sent when user active end the session. */ +#ifndef RYM_END_SESSION_SEND_CAN_NUM +#define RYM_END_SESSION_SEND_CAN_NUM 0x03 +#endif + +/* Exported constants --------------------------------------------------------*/ +/* Packet structure defines */ +#define PACKET_HEADER_SIZE ((uint32_t)3) +#define PACKET_DATA_INDEX ((uint32_t)4) +#define PACKET_START_INDEX ((uint32_t)1) +#define PACKET_NUMBER_INDEX ((uint32_t)2) +#define PACKET_CNUMBER_INDEX ((uint32_t)3) +#define PACKET_TRAILER_SIZE ((uint32_t)2) +#define PACKET_OVERHEAD_SIZE (PACKET_HEADER_SIZE + PACKET_TRAILER_SIZE - 1) +#define PACKET_SIZE ((uint32_t)128) +#define PACKET_1K_SIZE ((uint32_t)1024) +#define _RYM_SOH_PKG_SZ (PACKET_SIZE + PACKET_HEADER_SIZE + PACKET_TRAILER_SIZE) +#define _RYM_STX_PKG_SZ (PACKET_1K_SIZE + PACKET_HEADER_SIZE + PACKET_TRAILER_SIZE) +#define _RYM_PKG_SZ _RYM_STX_PKG_SZ // 这里定义的是数据包的大小 + +/* 因为data是需要写入到flash里面,如果不对齐,会出现UNALIGNED异常 + * /-------- Packet in IAP memory ------------------------------------------\ + * | 0 | 1 | 2 | 3 | 4 | ... | n+4 | n+5 | n+6 | + * |------------------------------------------------------------------------| + * | unused | start | number | !num | data[0] | ... | data[n] | crc0 | crc1 | + * \------------------------------------------------------------------------/ + * the first byte is left unused for memory alignment reasons */ + +#define FILE_NAME_LENGTH ((uint32_t)64) +#define FILE_SIZE_LENGTH ((uint32_t)16) + +#define NEGATIVE_BYTE ((uint8_t)0xFF) + +#define ABORT1 ((uint8_t)0x41) /* 'A' == 0x41, abort by user */ +#define ABORT2 ((uint8_t)0x61) /* 'a' == 0x61, abort by user */ + +#define MAX_ERRORS ((uint32_t)5) + +enum rym_stage +{ + RYM_STAGE_NONE, + /* set when C is send */ + RYM_STAGE_ESTABLISHING, + /* set when we've got the packet 0 and sent ACK and second C */ + RYM_STAGE_ESTABLISHED, + /* set when the sender respond to our second C and recviever got a real + * data packet. */ + RYM_STAGE_TRANSMITTING, + /* set when the sender send a EOT */ + RYM_STAGE_FINISHING, + /* set when transmission is really finished, i.e., after the NAK, C, final + * NULL packet stuff. */ + RYM_STAGE_FINISHED, +}; + +/* when receiving files, the buf will be the data received from ymodem protocol + * and the len is the data size. + * + * TODO: + * When sending files, the len is the buf size in RYM. The callback need to + * fill the buf with data to send. Returning RYM_CODE_EOT will terminate the + * transfer and the buf will be discarded. Any other return values will cause + * the transfer continue. + */ +typedef enum rym_code (*rym_callback)(uint8_t *buf, uint32_t len); + +/** recv a file on device dev with ymodem session ctx. + * + * If an error happens, you can get where it is failed from ctx->stage. + * + * @param on_begin The callback will be invoked when the first packet arrived. + * This packet often contain file names and the size of the file, if the sender + * support it. So if you want to save the data to a file, you may need to + * create the file on need. It is the on_begin's responsibility to parse the + * data content. The on_begin can be NULL, in which case the transmission will + * continue without any side-effects. + * + * @param on_data The callback will be invoked on the packets received. The + * callback should save the data to the destination. The return value will be + * sent to the sender and in turn, only RYM_{ACK,CAN} is valid. When on_data is + * NULL, RYM will barely send ACK on every packet and have no side-effects. + * + * @param on_end The callback will be invoked when one transmission is + * finished. The data should be 128 bytes of NULL. You can do some cleaning job + * in this callback such as closing the file. The return value of this callback + * is ignored. As above, this parameter can be NULL if you don't need such + * function. + * + * @param handshake_timeout the timeout when hand shaking. The unit is in + * second. + */ +BOOL rym_config(rym_callback on_begin, rym_callback on_data, + rym_callback on_end, rym_callback on_transmit, + int handshake_timeout); + +/** + * @brief Initializes the YMODEM protocol for receiving data. + * + * @return BOOL Returns TRUE if initialization is successful, FALSE otherwise. + */ +BOOL rym_init(void); + +/** + * @brief Receives data using the YMODEM protocol. + * + * @param p Pointer to the buffer where the received data will be stored. + * @param size The size of the buffer. + * @return uint16_t The number of bytes received. + */ +uint16_t rym_receive(void *p, uint16_t size); + +/** + * @brief Processes the received data using the YMODEM protocol. + */ +void rym_process(void); + +/** + * @brief Checks if a timeout has occurred during the YMODEM protocol. + * + * @return BOOL Returns TRUE if a timeout has occurred, FALSE otherwise. + */ +BOOL rym_timeout(void); + +#endif diff --git a/User/lib/control/custom/pid_c.c b/User/lib/control/custom/pid_c.c new file mode 100644 index 0000000..4354fbc --- /dev/null +++ b/User/lib/control/custom/pid_c.c @@ -0,0 +1,38 @@ +#include "pid_c.h" + +/** + * @brief 设置PID控制器参数 + * @param {PID_C} *self - PID控制器结构体指针 + * @param {float32} kp - 比例系数 + * @param {float32} ki - 积分系数 + * @param {float32} kd - 微分系数 + * @param {float32} out_min - 最小输出 + * @param {float32} out_max - 最大输出 + * @return {*} - 空 + */ +static void _set_ctrl_prm(struct PID_C *self, float32 kp, float32 ki, float32 kd, float32 out_min, float32 out_max) +{ + self->pri.kp = kp; /*比例系数*/ + self->pri.ki = ki; /*积分系数*/ + self->pri.kd = kd; /*微分系数*/ + + self->pri.deadband = 0.5; /*死区*/ + self->pri.maximum = out_max; /*最大输出*/ + self->pri.minimum = out_min; /*最小输出*/ + self->pri.last_error = 0; /*上一次误差*/ + self->pri.prev_error = 0; /*上上次误差*/ +} + +static float32 _PID(struct PID_C *self, float32 target, float32 feedback) +{ + /** + * 实现PID算法 + */ + return 0; +} + +void pid_c_constructor(struct PID_C *self) +{ + self->set_ctrl_prm = _set_ctrl_prm; + self->PID = _PID; +} diff --git a/User/lib/control/custom/pid_c.h b/User/lib/control/custom/pid_c.h new file mode 100644 index 0000000..ccc7e86 --- /dev/null +++ b/User/lib/control/custom/pid_c.h @@ -0,0 +1,34 @@ +#ifndef __PID_C_H__ +#define __PID_C_H__ +#include "lib.h" + +typedef struct PID_C +{ + /* 设置PID三个参数 */ + void (*set_ctrl_prm)(struct PID_C *self, float32 kp, float32 ki, float32 kd, float32 out_min, float32 out_max); + /* 控制接口 */ + float32 (*PID)(struct PID_C *self, float32 target, float32 feedback); + + // 自定义参数 + /* 实际值与目标值之间的误差 */ + float32 err; + /* 输出值 */ + float32 out; + /* private */ + struct + { + float32 kp; /*比例学习速度*/ + float32 ki; /*积分学习速度*/ + float32 kd; /*微分学习速度*/ + float32 ki_error; /*积分误差*/ + float32 last_error; /*前一拍偏差*/ + float32 prev_error; /*前两拍偏差*/ + float32 deadband; /*死区*/ + float32 maximum; /*输出值的上限*/ + float32 minimum; /*输出值的下限*/ + } pri; +} pid_c_t; + +extern void pid_c_constructor(struct PID_C *self); + +#endif // __PID_C_H__ diff --git a/User/lib/control/custom/pid_g.c b/User/lib/control/custom/pid_g.c new file mode 100644 index 0000000..0759d5f --- /dev/null +++ b/User/lib/control/custom/pid_g.c @@ -0,0 +1,250 @@ +#include "pid_g.h" +#include + +/** + * @brief 复位PID积分及微分控制数据 + * @param {PID_G} *self + * @return {*} + */ +static void _restctrl(struct PID_G *self) +{ + self->pri.pre_error = 0; + self->pri.sum_iterm = 0; +} + +/** + * @brief 更新控制区间 + * @param {PID_G} *self + * @param {float32} out_min + * @param {float32} out_max + * @return {*} + * @note + */ +static void _set_range(struct PID_G *self, float32 out_min, float32 out_max) +{ + self->pri.out_max = out_max; + self->pri.out_min = out_min; +} + +/** + * @brief 更新kp + * @param {PID_G} *self + * @param {float32} kp + * @return {*} + * @note + */ +static void _set_kp(struct PID_G *self, float32 kp) +{ + self->pri.kp = kp; +} + +/** + * @brief 更新ki + * @param {PID_G} *self + * @param {float32} ki + * @return {*} + * @note + */ +static void _set_ki(struct PID_G *self, float32 ki) +{ + self->pri.ki = ki; +} + +/** + * @brief 更新kd + * @param {PID_G} *self + * @param {float32} kd + * @return {*} + * @note + */ +static void _set_kd(struct PID_G *self, float32 kd) +{ + self->pri.kd = kd; +} + +/** + * @brief 使能积分控制 + * @param {PID_G} *self + * @param {BOOL} enable + * @return {*} + * @note + */ +static void _set_ki_enable(struct PID_G *self, BOOL enable) +{ + self->pri.ki_enable = enable; +} + +/** + * @brief 使能微分控制 + * @param {PID_G} *self + * @param {BOOL} enable + * @return {*} + * @note + */ +static void _set_kd_enable(struct PID_G *self, BOOL enable) +{ + self->pri.kd_enable = enable; +} + +/** + * @brief 初始化控制参数 + * @return {*} + * @note + */ +static void _set_ctrl_prm(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max) +{ + g_param_t *pri = &self->pri; + osel_memset((uint8_t *)pri, 0, sizeof(pid_g_t)); + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; + pri->detach = FALSE; +} + +static void _update_ctrl_prm(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max) +{ + g_param_t *pri = &self->pri; + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; + pri->detach = FALSE; +} + +/** + * @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID + * @param {PID_G} *self + * @param {float32} max_err + * @param {BOOL} mode + * @return {*} + */ +static void _set_cfg(struct PID_G *self, float32 max_err, BOOL mode) +{ + self->pri.err_limit = max_err; + self->pri.detach = mode == FALSE ? FALSE : TRUE; +} + +/** + * @brief PID算法函数 + * @param {PID_G} *self + * @param {float32} target + * @param {float32} feedback + * @return {*} + * @note + */ +static float32 _PID(struct PID_G *self, float32 target, float32 feedback) +{ + float32 error = 0.0f; + float32 insert = 0.0f; + float32 temp_iterm = 0.0f; + float32 temp_kd = 0.0f; + + g_param_t *pri = &self->pri; + + pri->ref = target; + pri->feed_back = feedback; + pri->error = pri->ref - pri->feed_back; + error = pri->error; + if (fabs(pri->error) <= pri->err_dead) + { + error = 0; + } + + /*根据PID配置的模式,获取积分数据,进行积分累加*/ + if (pri->out >= pri->out_max) + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + if (error < 0) + { + temp_iterm = pri->ki * error; + } + } + } + else if (pri->out <= pri->out_min) + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + if (error > 0) + { + temp_iterm = pri->ki * error; + } + } + } + else + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + temp_iterm = pri->ki * error; + } + } + if (pri->ki_enable == FALSE) + { + insert = 0; + } + + /* integral */ + pri->sum_iterm += temp_iterm; + + if (pri->sum_iterm > pri->out_max) + { + pri->sum_iterm = pri->out_max; + } + else if (pri->sum_iterm < pri->out_min) + { + pri->sum_iterm = pri->out_min; + } + + /* differential */ + if (pri->kd_enable == TRUE) + { + temp_kd = pri->kd; + } + else + { + temp_kd = 0; + } + + pri->out = pri->kp * pri->error + pri->sum_iterm * insert + (pri->error - pri->pre_error) * temp_kd; + pri->pre_error = pri->error; + pri->pre_feed_back = pri->feed_back; + + /*limt pid output*/ + pri->out = RANGE(pri->out, pri->out_min, pri->out_max); + return pri->out; +} + +void pid_g_constructor(struct PID_G *self) +{ + self->set_ctrl_prm = _set_ctrl_prm; + self->update_ctrl_prm = _update_ctrl_prm; + self->set_cfg = _set_cfg; + self->set_kp = _set_kp; + self->set_ki_enable = _set_ki_enable; + self->set_ki = _set_ki; + self->set_kd_enable = _set_kd_enable; + self->set_kd = _set_kd; + self->set_range = _set_range; + self->restctrl = _restctrl; + self->PID = _PID; +} diff --git a/User/lib/control/custom/pid_g.h b/User/lib/control/custom/pid_g.h new file mode 100644 index 0000000..c16b96d --- /dev/null +++ b/User/lib/control/custom/pid_g.h @@ -0,0 +1,61 @@ +#ifndef __PID_G_H__ +#define __PID_G_H__ +#include "lib.h" + +typedef struct +{ + float32 ref; /*目标*/ + float32 feed_back; /*实际*/ + float32 pre_feed_back; /*上一次实际*/ + float32 kp; /*比例学习速度*/ + float32 ki; /*积分学习速度*/ + float32 kd; /*微分学习速度*/ + float32 ki_error; /*积分误差*/ + float32 error; /*误差*/ + float32 pre_error; /*前一拍偏差*/ + float32 prev_error; /*前两拍偏差*/ + float32 err_dead; /*死区*/ + float32 err_limit; /*积分分离上限*/ + float32 maximum; /*输出值的上限*/ + float32 minimum; /*输出值的下限*/ + float32 out; /*输出值*/ + float32 sum_iterm; /*积分累加*/ + BOOL ki_enable; /*积分使能*/ + BOOL kd_enable; /*微分使能*/ + BOOL detach; + uint16_t out_max; + uint16_t out_min; +} g_param_t; + +typedef struct PID_G +{ + /* 设置PID三个参数 */ + void (*set_ctrl_prm)(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max); + /* 更新PID参数 */ + void (*update_ctrl_prm)(struct PID_G *self, float32 kp, float32 ki, float32 kd, float32 err_dead, float32 out_min, float32 out_max); + /* 控制接口 */ + float32 (*PID)(struct PID_G *self, float32 target, float32 feedback); + /* 更新控制区间 */ + void (*set_range)(struct PID_G *self, float32 out_min, float32 out_max); + /* 设置积分分离 */ + void (*set_cfg)(struct PID_G *self, float32 max_err, BOOL mode); + /* 更新kp */ + void (*set_kp)(struct PID_G *self, float32 kp); + /* 使能ki */ + void (*set_ki_enable)(struct PID_G *self, BOOL enable); + /* 更新ki */ + void (*set_ki)(struct PID_G *self, float32 ki); + /* 使能kd */ + void (*set_kd_enable)(struct PID_G *self, BOOL enable); + /* 更新kd */ + void (*set_kd)(struct PID_G *self, float32 kd); + /* 复位PID积分及微分控制数据 */ + void (*restctrl)(struct PID_G *self); + + /* private */ + g_param_t pri; + +} pid_g_t; + +extern void pid_g_constructor(struct PID_G *self); +#endif // __PID_G_H__ diff --git a/User/lib/control/custom/pid_hd.c b/User/lib/control/custom/pid_hd.c new file mode 100644 index 0000000..d151da6 --- /dev/null +++ b/User/lib/control/custom/pid_hd.c @@ -0,0 +1,180 @@ +#include "pid_hd.h" +#include +#include "sys.h" +#include "app.h" + +float32 out_pos; // 位置式pid输出 +float32 Kp_watch; // 观测Kp的大小 +float32 Ki_watch; // 观测Kp的大小 +float32 Kd_watch; // 观测Kp的大小 + +#if INCOMPLETE_DIFFEREN_HD == 1 // 积分分离 +/*计算微分项,使用追随误差微分项*/ +static float32 td_derivative(struct PID_HD *self, float32 current_err, float32 pre_err, float32 dt) +{ + pid_hd_position_t *pri = &self->pri_u.position; + float32 derivative = (current_err - pre_err) / dt; // 计算积分项 + derivative = pri->td_alpha * derivative + (1 - pri->td_alpha) * pri->td_beta * pri->pre_derivative; // 追随误差微分器平滑输出 + pri->pre_derivative = derivative; // 更新上一次误差 + return derivative; +} +#endif + +/*杭电:设置增量式PID参数*/ +static void _set_ctrl_prm_position(struct PID_HD *self, float32 kp, float32 ki, float32 kd) +{ + pid_hd_position_t *pri = &self->pri_u.position; + osel_memset((uint8_t *)pri, 0, sizeof(pid_hd_position_t)); + + /*观测传进来的Kp、Ki、Kd*/ + Kp_watch = kp; + Ki_watch = ki; + Kd_watch = kd; + + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->ki_limit = 10; // 积分分离界限 + pri->err_dead = 0.5; // 控制死区范围 +#if INCOMPLETE_DIFFEREN_HD == 1 + /*不完全微分系数*/ + pri->td_alpha = 0.5; + pri->td_beta = 0.5; +#endif +} + +/*杭电:设置输出限幅参数*/ +static void _set_out_prm_position(struct PID_HD *self, float32 maximum, float32 minimum) +{ + self->pri_u.position.out_max = maximum; + self->pri_u.position.out_min = minimum; +} + +float32 out_pos_watch; +/*杭电:位置式PID控制算法*/ +static float32 _pid_position(struct PID_HD *self, float32 err) +{ + /*计算控制的运行时间*/ + sys_millis_reset(); + self->pri_u.position.control_time = sys_millis(); + self->pri_u.position.tmp_time = 0; + + /*测试:4.18*/ + if (fabs(err) < 0.1) + { + err = 0; + } + + float32 x[3]; + self->pri_u.position.err = err; + + /*抗积分饱和*/ +#if INTEGRAL_SEPARATION == 1 // 积分分离 + if (self->pri_u.position.out > self->pri_u.position.out_max) + { + if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 积分分离 + { + self->pri_u.position.ki_error += 0; + } + else + { + if (self->pri_u.position.err < 0) // 若偏差为负值,执行负偏差的累加 + { + self->pri_u.position.ki_error += self->pri_u.position.err; + } + } + } + else if (self->pri_u.position.out < self->pri_u.position.out_min) + { + if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 若偏差为负值,停止积分 + { + self->pri_u.position.ki_error += 0; + } + else + { + if (self->pri_u.position.err > 0) // 若偏差为正值,执行正偏差的累加 + { + self->pri_u.position.ki_error += self->pri_u.position.err; + } + } + } + else + { + if (fabs(err) > self->pri_u.position.ki_limit || fabs(err) < 0.5) + { + self->pri_u.position.ki_error += 0; + } + else + { + self->pri_u.position.ki_error += self->pri_u.position.err; + } + } +#else /*无积分分离操作*/ + if (fabs(err) < 0.4) + { + self->pri_u.position.ki_error += 0; + } + else + { + self->pri_u.position.ki_error += self->pri_u.position.err; + } +#endif + + /*输出*/ + if (fabs(err) < self->pri_u.position.err_dead) + { + /*输出上一次的值*/ + // self->pri_u.position.out = self->pri_u.position.pre_out; + x[0] = self->pri_u.position.err; + x[1] = self->pri_u.position.ki_error; + out_pos = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2]; + out_pos_watch = out_pos; + self->pri_u.position.out = out_pos; + } + else + { + x[0] = self->pri_u.position.err; + x[1] = self->pri_u.position.ki_error; + +#if INCOMPLETE_DIFFEREN_HD == 1 + /*不完全微分项,为了解决普通PID为微分环节容易振荡的问题*/ + self->pri_u.position.tmp_time = sys_millis(); + self->pri_u.position.control_time -= self->pri_u.position.tmp_time; + self->pri_u.position.control_time /= 1000.0; // 将单位转换为秒 + x[2] = td_derivative(&_pid.pid_u.hd, err, self->pri_u.position.pre_error, self->pri_u.position.control_time); +#else + // 普通的微分环节 + x[2] = self->pri_u.position.err - self->pri_u.position.pre_error; +#endif + + out_pos = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2]; + out_pos_watch = out_pos; + self->pri_u.position.out = out_pos; + } + + /*输出限幅*/ + if (self->pri_u.position.out > self->pri_u.position.out_max) + { + self->pri_u.position.out = self->pri_u.position.out_max; + } + if (self->pri_u.position.out < self->pri_u.position.out_min) + { + self->pri_u.position.out = self->pri_u.position.out_min; + } + + // 更新误差历史 + self->pri_u.position.pre_error = self->pri_u.position.err; /*上一次误差值*/ + // 更新输出历史 + self->pri_u.position.pre_out = self->pri_u.position.out; /*上一次输出值*/ + + out_pos = self->pri_u.position.out; + return self->pri_u.position.out; +} + +/*杭电:参数控制器*/ +void pid_hd_constructor(struct PID_HD *self) +{ + self->set_ctrl_prm_position = _set_ctrl_prm_position; + self->set_out_prm_position = _set_out_prm_position; + self->pid_position = _pid_position; +} diff --git a/User/lib/control/custom/pid_hd.h b/User/lib/control/custom/pid_hd.h new file mode 100644 index 0000000..2fa96f0 --- /dev/null +++ b/User/lib/control/custom/pid_hd.h @@ -0,0 +1,66 @@ +#ifndef __PID_HD__ +#define __PID_HD__ +#include "lib.h" + +#define INTEGRAL_SEPARATION 1 // 积分分离 +#define INCOMPLETE_DIFFEREN_HD 1 // 不完全微分 + +typedef struct +{ + float32 ref; + float32 feed_back; + float32 pre_feed_back; + float32 pre_error; + float32 ki_error; /*积分误差*/ + float32 ki_limit; /*积分分离界限*/ + float32 ki_alpha; /*变积分的系数*/ + float32 err; + float32 sum_iterm; + float32 kp; + float32 kp_small; /*在接近稳态时的Kp*/ + float32 kp_big; /*在大范围时的Kp*/ + float32 ki; + float32 kd; + float32 err_limit; + BOOL detach; + float32 err_dead; +#if INCOMPLETE_DIFFEREN_HD == 1 + float32 td_alpha; /*不完全微分系数*/ + float32 td_beta; /*不完全微分系数beta*/ + float32 pre_derivative; /*上一次微分值*/ +#endif + float32 out; + float32 pre_out; + float32 out_max; + float32 out_min; + BOOL sm; + float32 sv_range; + uint32_t control_time; /*控制算法运行一次花费的时间*/ + uint32_t tmp_time; /*临时用来记录控制的运行时间*/ +} pid_hd_position_t; // 位置式PID + +typedef struct PID_HD +{ + /* 设置PID三个参数 */ + void (*set_ctrl_prm_position)(struct PID_HD *self, float32 kp, float32 ki, float32 kd); + /* 设置输出范围 */ + void (*set_out_prm_position)(struct PID_HD *self, float32 maximum, float32 minimum); + + /* 控制接口 */ + float32 (*pid_position)(struct PID_HD *self, float32 err); + + // 自定义参数 + /* 实际值与目标值之间的误差 */ + float32 err; + /* 输出值 */ + float32 out; + /* private */ + struct + { + pid_hd_position_t position; + } pri_u; +} pid_hd_t; + +extern void pid_hd_constructor(struct PID_HD *self); + +#endif // __PID_HD__ diff --git a/User/lib/control/custom/pid_x.c b/User/lib/control/custom/pid_x.c new file mode 100644 index 0000000..177d563 --- /dev/null +++ b/User/lib/control/custom/pid_x.c @@ -0,0 +1,481 @@ +#include "pid_x.h" +#include "math.h" +#define LAG_PHASE (6) // 迟滞相位,单位:拍 + +#ifndef PI +#define PI 3.14159265358979f +#endif +// 注1:自适应模糊pid最重要的就是论域的选择,要和你应该控制的对象相切合 +// 注2:以下各阀值、限幅值、输出值均需要根据具体的使用情况进行更改 +// 注3:因为我的控制对象惯性比较大,所以以下各部分取值较小 +// 论域e:[-5,5] ec:[-0.5,0.5] + +// 误差的阀值,小于这个数值的时候,不做PID调整,避免误差较小时频繁调节引起震荡 +#define Emin 0.3f +#define Emid 1.0f +#define Emax 5.0f +// 调整值限幅,防止积分饱和 +#define Umax 1 +#define Umin -1 + +#define NB 0 +#define NM 1 +#define NS 2 +#define ZO 3 +#define PS 4 +#define PM 5 +#define PB 6 + +int32_t kp[7][7] = {{PB, PB, PM, PM, PS, ZO, ZO}, + {PB, PB, PM, PS, PS, ZO, ZO}, + {PM, PM, PM, PS, ZO, NS, NS}, + {PM, PM, PS, ZO, NS, NM, NM}, + {PS, PS, ZO, NS, NS, NM, NM}, + {PS, ZO, NS, NM, NM, NM, NB}, + {ZO, ZO, NM, NM, NM, NB, NB}}; + +int32_t kd[7][7] = {{PS, NS, NB, NB, NB, NM, PS}, + {PS, NS, NB, NM, NM, NS, ZO}, + {ZO, NS, NM, NM, NS, NS, ZO}, + {ZO, NS, NS, NS, NS, NS, ZO}, + {ZO, ZO, ZO, ZO, ZO, ZO, ZO}, + {PB, NS, PS, PS, PS, PS, PB}, + {PB, PM, PM, PM, PS, PS, PB}}; + +int32_t ki[7][7] = {{NB, NB, NM, NM, NS, ZO, ZO}, + {NB, NB, NM, NS, NS, ZO, ZO}, + {NB, NM, NS, NS, ZO, PS, PS}, + {NM, NM, NS, ZO, PS, PM, PM}, + {NM, NS, ZO, PS, PS, PM, PB}, + {ZO, ZO, PS, PS, PM, PB, PB}, + {ZO, ZO, PS, PM, PM, PB, PB}}; + +static float32 ec; // 误差变化率 +/**************求隶属度(三角形)***************/ +float32 FTri(float32 x, float32 a, float32 b, float32 c) // FuzzyTriangle +{ + if (x <= a) + return 0; + else if ((a < x) && (x <= b)) + return (x - a) / (b - a); + else if ((b < x) && (x <= c)) + return (c - x) / (c - b); + else if (x > c) + return 0; + else + return 0; +} +/*****************求隶属度(梯形左)*******************/ +float32 FTraL(float32 x, float32 a, float32 b) // FuzzyTrapezoidLeft +{ + if (x <= a) + return 1; + else if ((a < x) && (x <= b)) + return (b - x) / (b - a); + else if (x > b) + return 0; + else + return 0; +} +/*****************求隶属度(梯形右)*******************/ +float32 FTraR(float32 x, float32 a, float32 b) // FuzzyTrapezoidRight +{ + if (x <= a) + return 0; + if ((a < x) && (x < b)) + return (x - a) / (b - a); + if (x >= b) + return 1; + else + return 1; +} +/****************三角形反模糊化处理**********************/ +float32 uFTri(float32 x, float32 a, float32 b, float32 c) +{ + float32 y, z; + z = (b - a) * x + a; + y = c - (c - b) * x; + return (y + z) / 2; +} +/*******************梯形(左)反模糊化***********************/ +float32 uFTraL(float32 x, float32 a, float32 b) +{ + return b - (b - a) * x; +} +/*******************梯形(右)反模糊化***********************/ +float32 uFTraR(float32 x, float32 a, float32 b) +{ + return (b - a) * x + a; +} +/**************************求交集****************************/ +float32 fand(float32 a, float32 b) +{ + return (a < b) ? a : b; +} +/**************************求并集****************************/ +float32 forr(float32 a, float32 b) +{ + return (a < b) ? b : a; +} + +static float32 _PID(struct PID_X *self, float32 target, float32 feedback) +{ + float32 pwm_var; // pwm调整量 + float32 iError; // 当前误差 + float32 set, input; + CLASSICPID *pri = &self->pri; + // 计算隶属度表 + float32 es[7], ecs[7], e; + float32 form[7][7]; + int i = 0, j = 0; + int MaxX = 0, MaxY = 0; + + // 记录隶属度最大项及相应推理表的p、i、d值 + float32 lsd; + int temp_p, temp_d, temp_i; + float32 detkp, detkd, detki; // 推理后的结果 + + // 输入格式的转化及偏差计算 + set = target; + input = feedback; + iError = set - input; // 偏差 + + e = iError; + ec = iError - pri->lasterror; + + // 当温度差的绝对值小于Emax时,对pid的参数进行调整 + if (fabs(iError) <= Emax) + { + // 计算iError在es与ecs中各项的隶属度 + es[NB] = FTraL(e * 5, -3, -1); // e + es[NM] = FTri(e * 5, -3, -2, 0); + es[NS] = FTri(e * 5, -3, -1, 1); + es[ZO] = FTri(e * 5, -2, 0, 2); + es[PS] = FTri(e * 5, -1, 1, 3); + es[PM] = FTri(e * 5, 0, 2, 3); + es[PB] = FTraR(e * 5, 1, 3); + + ecs[NB] = FTraL(ec * 30, -3, -1); // ec + ecs[NM] = FTri(ec * 30, -3, -2, 0); + ecs[NS] = FTri(ec * 30, -3, -1, 1); + ecs[ZO] = FTri(ec * 30, -2, 0, 2); + ecs[PS] = FTri(ec * 30, -1, 1, 3); + ecs[PM] = FTri(ec * 30, 0, 2, 3); + ecs[PB] = FTraR(ec * 30, 1, 3); + + // 计算隶属度表,确定e和ec相关联后表格各项隶属度的值 + for (i = 0; i < 7; i++) + { + for (j = 0; j < 7; j++) + { + form[i][j] = fand(es[i], ecs[j]); + } + } + + // 取出具有最大隶属度的那一项 + for (i = 0; i < 7; i++) + { + for (j = 0; j < 7; j++) + { + if (form[MaxX][MaxY] < form[i][j]) + { + MaxX = i; + MaxY = j; + } + } + } + // 进行模糊推理,并去模糊 + lsd = form[MaxX][MaxY]; + temp_p = kp[MaxX][MaxY]; + temp_d = kd[MaxX][MaxY]; + temp_i = ki[MaxX][MaxY]; + + if (temp_p == NB) + detkp = uFTraL(lsd, -0.3, -0.1); + else if (temp_p == NM) + detkp = uFTri(lsd, -0.3, -0.2, 0); + else if (temp_p == NS) + detkp = uFTri(lsd, -0.3, -0.1, 0.1); + else if (temp_p == ZO) + detkp = uFTri(lsd, -0.2, 0, 0.2); + else if (temp_p == PS) + detkp = uFTri(lsd, -0.1, 0.1, 0.3); + else if (temp_p == PM) + detkp = uFTri(lsd, 0, 0.2, 0.3); + else if (temp_p == PB) + detkp = uFTraR(lsd, 0.1, 0.3); + + if (temp_d == NB) + detkd = uFTraL(lsd, -3, -1); + else if (temp_d == NM) + detkd = uFTri(lsd, -3, -2, 0); + else if (temp_d == NS) + detkd = uFTri(lsd, -3, 1, 1); + else if (temp_d == ZO) + detkd = uFTri(lsd, -2, 0, 2); + else if (temp_d == PS) + detkd = uFTri(lsd, -1, 1, 3); + else if (temp_d == PM) + detkd = uFTri(lsd, 0, 2, 3); + else if (temp_d == PB) + detkd = uFTraR(lsd, 1, 3); + + if (temp_i == NB) + detki = uFTraL(lsd, -0.06, -0.02); + else if (temp_i == NM) + detki = uFTri(lsd, -0.06, -0.04, 0); + else if (temp_i == NS) + detki = uFTri(lsd, -0.06, -0.02, 0.02); + else if (temp_i == ZO) + detki = uFTri(lsd, -0.04, 0, 0.04); + else if (temp_i == PS) + detki = uFTri(lsd, -0.02, 0.02, 0.06); + else if (temp_i == PM) + detki = uFTri(lsd, 0, 0.04, 0.06); + else if (temp_i == PB) + detki = uFTraR(lsd, 0.02, 0.06); + + // pid三项系数的修改 + pri->pKp += detkp; + pri->pKi += detki; + if (pri->kd_e) + { + pri->pKd += detkd; + } + else + { + pri->pKd = 0; // 取消微分作用 + } + + // 对Kp,Ki进行限幅 + if (pri->pKp < 0) + { + pri->pKp = 0; + } + if (pri->pKi < 0) + { + pri->pKi = 0; + } + + // 计算新的K1,nKi,nKd + pri->nKp = pri->pKp + pri->pKi + pri->pKd; + pri->nKi = -(pri->pKp + 2 * pri->pKd); + pri->nKd = pri->pKd; + } + + if (iError > Emax) + { + pri->out = pri->max; + pwm_var = 0; + pri->flag = 1; // 设定标志位,如果误差超过了门限值,则认为当控制量第一次到达给定值时,应该采取下面的 抑制超调 的措施 + } + else if (iError < -Emax) + { + pri->out = pri->min; + pwm_var = 0; + } + else if (fabsf(iError) <= Emin) + { + pwm_var = 0; + } + else + { + if (iError < Emid && pri->flag == 1) // 第一次超过(设定值-Emid(-0.08)摄氏度),是输出为零,防止超调,也可以输出其他值,不至于太小而引起震荡 + { + pri->out = 0; + pri->flag = 0; + } + else if (-iError > Emid) // 超过(设定+Emid(+0.08)摄氏度) + { + pwm_var = -1; + } + else + { + // 增量计算 + pwm_var = (pri->nKp * iError // e[k] + + pri->nKi * pri->lasterror // e[k-1] + + pri->nKd * pri->preverror); // e[k-2] + } + if (pwm_var >= Umax) + pwm_var = Umax; // 调整值限幅,防止积分饱和 + if (pwm_var <= Umin) + pwm_var = Umin; // 调整值限幅,防止积分饱和 + } + pri->preverror = pri->lasterror; + pri->lasterror = iError; + + pri->out += pwm_var; // 调整PWM输出 + + if (pri->out > pri->max) + pri->out = pri->max; // 输出值限幅 + if (pri->out < pri->min) + pri->out = pri->min; // 输出值限幅 + + return pri->out; +} + +/*整定开始前的预处理,判断状态及初始化变量*/ +static void tune_pretreatment(struct PID_X *self) +{ + CLASSIC_AUTOTUNE *tune = &self->tune; + CLASSICPID *vPID = &self->pri; + + tune->tuneTimer = 0; + tune->startTime = 0; + tune->endTime = 0; + tune->outputStep = 100; + + if (*vPID->pSV >= *vPID->pPV) + { + tune->initialStatus = 1; + tune->outputStatus = 0; + } + else + { + tune->initialStatus = 0; + tune->outputStatus = 1; + } + tune->tuneEnable = 1; + tune->preEnable = 0; + tune->zeroAcrossCounter = 0; + tune->riseLagCounter = 0; + tune->fallLagCounter = 0; +} + +/*计算PID参数值*/ +static void calculation_parameters(struct PID_X *self) +{ + CLASSIC_AUTOTUNE *tune = &self->tune; + CLASSICPID *vPID = &self->pri; + float32 kc = 0.0; + float32 tc = 0.0; + float32 zn[3][3] = {{0.5, 100000.0, 0.0}, {0.45, 0.8, 0.0}, {0.6, 0.5, 0.125}}; + + tc = (tune->endTime - tune->startTime) * tune->tunePeriod / 1000.0; + kc = (8.0 * tune->outputStep) / (PI * (tune->maxPV - tune->minPV)); + + vPID->pKp = zn[tune->controllerType][0] * kc; // 比例系数 + vPID->pKi = vPID->pKp * tune->tunePeriod / (zn[tune->controllerType][1] * tc); // 积分系数 + vPID->pKd = vPID->pKp * zn[tune->controllerType][2] * tc / tune->tunePeriod; // 微分系数 +} + +/** + * @brief 自整定函数 + * @param {PID_X} *self + * @return {*} + * @note 成员变量tuneEnable、preEnable和controllerType需要提前赋值。tuneEnable变量值为0时是使用PID控制器,而tuneEnable变量值为1时是开启整定过程,当tuneEnable变量值为2时是指示整定失败。preEnable变量在整定前赋值为1,表示先做预处理。而controllerType则根据所整定的控制器的类型来定,主要用于参数的计算。 + */ +static uint8_t _auto_tune(struct PID_X *self) +{ + CLASSIC_AUTOTUNE *tune = &self->tune; + CLASSICPID *vPID = &self->pri; + /*整定开始前的预处理,只执行一次*/ + if (tune->preEnable == 1) + { + tune_pretreatment(self); + } + + uint32_t tuneDuration = 0; + tune->tuneTimer++; + tuneDuration = (tune->tuneTimer * tune->tunePeriod) / 1000; + if (tuneDuration > (10 * 60)) // 整定过程持续超过10分钟,未能形成有效振荡,整定失败 + { + tune->tuneEnable = 2; + tune->preEnable = 1; + return tune->tuneEnable; + } + + if (*vPID->pSV >= *vPID->pPV) // 设定值大于测量值,则开执行单元 + { + tune->riseLagCounter++; + tune->fallLagCounter = 0; + + if (tune->riseLagCounter > LAG_PHASE) + { + *vPID->pMV = vPID->max; + if (tune->outputStatus == 0) + { + tune->outputStatus = 1; + tune->zeroAcrossCounter++; + + if (tune->zeroAcrossCounter == 3) + { + tune->startTime = tune->tuneTimer; + } + } + } + } + else + { + tune->riseLagCounter = 0; + tune->fallLagCounter++; + + if (tune->fallLagCounter > LAG_PHASE) + { + *vPID->pMV = vPID->min; + if (tune->outputStatus == 1) + { + tune->outputStatus = 0; + tune->zeroAcrossCounter++; + + if (tune->zeroAcrossCounter == 3) + { + tune->startTime = tune->tuneTimer; + } + } + } + } + + if (tune->zeroAcrossCounter == 3) // 已经两次过零,可以记录波形数据 + { + if (tune->initialStatus == 1) // 初始设定值大于测量值,则区域3出现最小值 + { + if (*vPID->pPV < tune->minPV) + { + tune->minPV = *vPID->pPV; + } + } + else if (tune->initialStatus == 0) // 初始设定值小于测量值,则区域3出现最大值 + { + if (*vPID->pPV > tune->maxPV) + { + tune->maxPV = *vPID->pPV; + } + } + } + else if (tune->zeroAcrossCounter == 4) // 已经三次过零,记录另半波的数据 + { + if (tune->initialStatus == 1) // 初始设定值大于测量值,则区域4出现最大值 + { + if (*vPID->pPV > tune->maxPV) + { + tune->maxPV = *vPID->pPV; + } + } + else if (tune->initialStatus == 0) // 初始设定值小于测量值,则区域4出现最小值 + { + if (*vPID->pPV < tune->minPV) + { + tune->minPV = *vPID->pPV; + } + } + } + else if (tune->zeroAcrossCounter == 5) // 已经四次过零,振荡已形成可以整定参数 + { + calculation_parameters(self); + + tune->tuneEnable = 0; + tune->preEnable = 1; + } + + return tune->tuneEnable; +} + +void pid_x_constructor(struct PID_X *self) +{ + self->PID = _PID; + self->AUTO_TUNE = _auto_tune; + self->pri.flag = 0; + self->pri.out = 0; + self->tune.preEnable = 1; +} diff --git a/User/lib/control/custom/pid_x.h b/User/lib/control/custom/pid_x.h new file mode 100644 index 0000000..2be7c04 --- /dev/null +++ b/User/lib/control/custom/pid_x.h @@ -0,0 +1,71 @@ +#ifndef __PID_X_H__ +#define __PID_X_H__ +#include "lib.h" + +/*定义PID对象类型*/ +typedef struct CLASSIC +{ + float32 *pPV; // 测量值指针 + float32 *pSV; // 设定值指针 + float32 *pMV; // 输出值指针 + BOOL *pMA; // 手自动操作指针 + + float32 out; // 输出值 + float32 setpoint; // 设定值 + float32 lasterror; // 前一拍偏差 + float32 preverror; // 前两拍偏差 + float32 max; // 输出值上限 + float32 min; // 输出值下限 + + uint16_t flag; // 状态标志位 + + float32 pKp; // 比例系数 + float32 pKi; // 积分系数 + float32 pKd; // 微分系数 + + float32 nKp; // 比例系数 + float32 nKi; // 积分系数 + float32 nKd; // 微分系数 + + BOOL direct; // 正反作用 + BOOL sm; // 设定值平滑 + BOOL cas; // 串级设定 + BOOL pac; // 输出防陡变 + BOOL kd_e; // 微分使能 +} CLASSICPID; + +// 定义整定参数 +typedef struct +{ + uint8_t tuneEnable : 2; // 整定与PID控制开关,0:PID控制;1:参数整定;2:整定失败 + uint8_t preEnable : 2; // 预处理使能,在开始整定前置位 + uint8_t initialStatus : 1; // 记录开始整定前偏差的初始状态 + uint8_t outputStatus : 1; // 记录输出的初始状态,0允许上升过零计数;1允许下降过零计数 + uint8_t controllerType : 2; // 控制器类型:0,P控制器;1,PI控制器;2,PID控制器 + + uint8_t zeroAcrossCounter; // 过零点计数器,每次输出改变加1,比实际过零次数多1 + uint8_t riseLagCounter; // 上升迟滞时间计数器 + uint8_t fallLagCounter; // 下降迟滞时间计数器 + + uint16_t tunePeriod; // 整定采样周期 + uint32_t tuneTimer; // 整定计时器 + uint32_t startTime; // 记录波形周期起始时间 + uint32_t endTime; // 记录波形周期结束时间 + + float32 outputStep; // 输出阶跃d + float32 maxPV; // 振荡波形中测量值的最大值 + float32 minPV; // 振荡波形中测量值的最小值 +} CLASSIC_AUTOTUNE; + +typedef struct PID_X +{ + /* 控制接口 */ + float32 (*PID)(struct PID_X *self, float32 target, float32 feedback); + uint8_t (*AUTO_TUNE)(struct PID_X *self); + /* private */ + CLASSICPID pri; + CLASSIC_AUTOTUNE tune; +} pid_x_t; + +extern void pid_x_constructor(struct PID_X *self); +#endif // __PID_X_H__ diff --git a/User/lib/control/custom/pid_zh.c b/User/lib/control/custom/pid_zh.c new file mode 100644 index 0000000..5a4ac54 --- /dev/null +++ b/User/lib/control/custom/pid_zh.c @@ -0,0 +1,432 @@ +#include "pid_zh.h" +#include "sys.h" +#include +// 定义输出量比例因子 +#define KUP 10.0f +#define KUI 0.03f +#define KUD 3.0f +// 模糊集合 +#define NL -3 +#define NM -2 +#define NS -1 +#define ZE 0 +#define PS 1 +#define PM 2 +#define PL 3 + +// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10 +#define MAXE (10) +#define MINE (-MAXE) +// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整, +#define MAXEC (10) +#define MINEC (-MAXEC) +// 定义e,ec的量化因子 +#define KE 3 / MAXE +#define KEC 3 / MAXEC + +static const float32 fuzzyRuleKp[7][7] = { + PL, PL, PM, PL, PS, PM, PL, + PL, PM, PM, PM, PS, PM, PL, + PM, PS, PS, PS, PS, PS, PM, + PM, PS, ZE, ZE, ZE, PS, PM, + PS, PS, PS, PS, PS, PM, PM, + PM, PM, PM, PM, PL, PL, PL, + PM, PL, PL, PL, PL, PL, PL}; +/* +static const float32 fuzzyRuleKi[7][7] = { + NL, NL, NL, NL, NM, NL, NL, + NL, NL, NM, NM, NM, NL, NL, + NM, NM, NS, NS, NS, NM, NM, + NM, NS, ZE, ZE, ZE, NS, NM, + NM, NS, NS, NS, NS, NM, NM, + NM, NM, NS, NM, NM, NL, NL, + NM, NL, NM, NL, NL, NL, NL}; +*/ +static const float32 fuzzyRuleKi[7][7] = { + PL, PL, PL, PL, PM, PL, PL, + PL, PL, PM, PM, PM, PL, PL, + PM, PM, PS, PS, PS, PM, PM, + PM, PS, ZE, ZE, ZE, PS, PM, + PM, PS, PS, PS, PS, PM, PM, + PM, PM, PS, PM, PM, PL, PL, + PM, PL, PM, PL, PL, PL, PL}; +/* +static const float32 fuzzyRuleKd[7][7] = { + PS, PS, ZE, ZE, ZE, PL, PL, + NS, NS, NS, NS, ZE, NS, PM, + NL, NL, NM, NS, ZE, PS, PM, + NL, NM, NM, NS, ZE, PS, PM, + NL, NM, NS, NS, ZE, PS, PS, + NM, NS, NS, NS, ZE, PS, PS, + PS, ZE, ZE, ZE, ZE, PL, PL}; +*/ +static const float32 fuzzyRuleKd[7][7] = { + PS, PS, ZE, ZE, ZE, PL, PL, + PS, PS, PS, PS, ZE, PS, PM, + PL, PL, PM, PS, ZE, PS, PM, + PL, PM, PM, PS, ZE, PS, PM, + PL, PM, PS, PS, ZE, PS, PS, + PM, PS, PS, PS, ZE, PS, PS, + PS, ZE, ZE, ZE, ZE, PL, PL}; + +static void fuzzy(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_pid) +{ + + float32 etemp, ectemp; + float32 eLefttemp, ecLefttemp; // ec,e,左隶属度 + float32 eRighttemp, ecRighttemp; + + int eLeftIndex, ecLeftIndex; // 模糊位置标号 + int eRightIndex, ecRightIndex; + e = RANGE(e, MINE, MAXE); + ec = RANGE(ec, MINEC, MAXEC); + e = e * KE; + ec = ec * KEC; + + etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f))))); + eLeftIndex = (int)((etemp - 0.5f) + 3); //[-3,3] -> [0,6] + eRightIndex = (int)((etemp + 0.5f) + 3); + eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e); + eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f)); + + ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f))))); + ecLeftIndex = (int)((ectemp - 0.5f) + 3); //[-3,3] -> [0,6] + ecRightIndex = (int)((ectemp + 0.5f) + 3); + ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec); + ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f)); + + /*************************************反模糊*************************************/ + + fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]); + + fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]); + + fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]); + // 对解算出的KP,KI,KD进行量化映射 + fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup; + fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui; + fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud; +} + +static void smoothSetpoint(struct PID_FUZZY_ZH *self, float32 target_sv) +{ +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_zh_position_t *pri = &self->pri; +#else + pid_common_increment_t *pri = &self->pri; +#endif + float32 stepIn = (pri->sv_range) * 0.1f; + float32 kFactor = 0.0f; + if (fabs(pri->ref - target_sv) <= stepIn) + { + pri->ref = target_sv; + } + else + { + if (pri->ref - target_sv > 0) + { + kFactor = -1.0f; + } + else if (pri->ref - target_sv < 0) + { + kFactor = 1.0f; + } + else + { + kFactor = 0.0f; + } + pri->ref = pri->ref + kFactor * stepIn; + } +} + +/*封装模糊接口*/ +static void compensate(float32 e, float32 ec, FUZZY_PID_ZH_t *fuzzy_d) +{ + fuzzy(e, ec, fuzzy_d); +} + +/** + * @brief 复位PID积分及微分控制数据 + * @param {PID_FUZZY_ZH} *self + * @return {*} + */ +static void _restctrl(struct PID_FUZZY_ZH *self) +{ + self->pri.pre_error = 0; + self->pri.sum_iterm = 0; +#if INCOMPLETE_DIFFEREN == 1 + self->pri.lastdev = 0; +#endif +} + +/** + * @brief 更新最大最小值 + * @param {PID_FUZZY_ZH} *self + * @param {float32} out_min + * @param {float32} out_max + * @return {*} + * @note + */ +static void _set_range(struct PID_FUZZY_ZH *self, float32 out_min, float32 out_max) +{ + self->pri.out_max = out_max; + self->pri.out_min = out_min; +} + +/** + * @brief 使能积分控制 + * @param {PID_FUZZY_ZH} *self + * @param {BOOL} enable + * @return {*} + * @note + */ +// static void _set_ki_enable(struct PID_FUZZY_ZH *self, BOOL enable) +// { +// self->pri.ki_enable = enable; +// } + +/** + * @brief 使能微分控制 + * @param {PID_FUZZY_ZH} *self + * @param {BOOL} enable + * @return {*} + * @note + */ +static void _set_kd_enable(struct PID_FUZZY_ZH *self, BOOL enable) +{ + self->pri.kd_enable = enable; +} + +/* + * Function:使能平滑控制 + * parameter:*pid需要配,PID参数结构指针,sv_range控制范围sv的范围 + * return:无 + */ +static void _set_smooth_enable(struct PID_FUZZY_ZH *self, BOOL enable, float32 sv_range) +{ +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_zh_position_t *pri = &self->pri; +#else + pid_common_increment_t *pri = &self->pri; +#endif + pri->sm = enable; + pri->sv_range = sv_range; +} + +// 设置控制参数 +static void _set_ctrl_prm(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max) +{ + self->open = TRUE; + self->fuzzy.kup = KUP; + self->fuzzy.kui = KUI; + self->fuzzy.kud = KUD; +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_zh_position_t *pri = &self->pri; + osel_memset((uint8_t *)pri, 0, sizeof(pid_zh_position_t)); + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; + pri->detach = FALSE; + pri->sm = FALSE; +#else + pid_common_increment_t *pri = &self->pri; + osel_memset((uint8_t *)pri, 0, sizeof(pid_common_increment_t)); + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; +#endif + + if (kd > 0) + { + pri->kd_enable = TRUE; + } + else + { + pri->kd_enable = FALSE; + } +} + +static void _update_ctrl_prm(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max) +{ +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_zh_position_t *pri = &self->pri; + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; + pri->detach = FALSE; + pri->sm = FALSE; +#else + pid_common_increment_t *pri = &self->pri; + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; +#endif + + if (kd > 0) + { + pri->kd_enable = TRUE; + } + else + { + pri->kd_enable = FALSE; + } +} + +/** + * @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID + * @param {PID_FUZZY_ZH} *self + * @param {float32} max_err + * @param {BOOL} mode + * @return {*} + */ +static void _set_cfg(struct PID_FUZZY_ZH *self, float32 max_err, BOOL mode) +{ + self->pri.err_limit = max_err; + self->pri.detach = mode == FALSE ? FALSE : TRUE; +} + +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION +static float32 _PID(struct PID_FUZZY_ZH *self, float32 target, float32 feedback) +{ + float32 error = 0; + float32 insert = 0; + float32 ec = 0; + float32 kd = 0; +#if INCOMPLETE_DIFFEREN == 1 + float32 thisdev = 0; +#else + // float32 dinput = 0.0f; +#endif + float32 temp_iterm = 0.0f; + pid_zh_position_t *pri = &self->pri; + + /*获取期望值与实际值,进行偏差计算*/ + if (pri->sm == 1) + { + smoothSetpoint(self, target); + } + else + { + pri->ref = target; + } + + pri->feed_back = feedback; + error = pri->ref - pri->feed_back; + if (fabs(error) <= pri->err_dead) + error = 0; + + /* fuzzy control caculate */ + ec = error - pri->pre_error; + if (self->open == TRUE) + { + compensate(error, ec, &self->fuzzy); + } + + /*根据PID配置的模式,获取积分数据,进行积分累加*/ + if (pri->out >= pri->out_max) + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + if (error < 0) + { + temp_iterm = (pri->ki + self->fuzzy.ki) * error; + } + } + } + else if (pri->out <= pri->out_min) + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + if (error > 0) + { + temp_iterm = (pri->ki + self->fuzzy.ki) * error; + } + } + } + else + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + temp_iterm = (pri->ki + self->fuzzy.ki) * error; + } + } + pri->sum_iterm += temp_iterm; + /* limt integral */ + if (pri->sum_ref) + pri->sum_iterm = RANGE(pri->sum_iterm, pri->sum_ref - 1.0f, pri->sum_ref + 1.0f); + else + pri->sum_iterm = RANGE(pri->sum_iterm, pri->out_min, pri->out_max); + +#if INCOMPLETE_DIFFEREN == 1 + /*不完全微分*/ + thisdev = (pri->kd + self->fuzzy.kd) * (1.0 - pri->alpha) * (error - pri->pre_error) + pri->alpha * pri->lastdev; + /*caculate pid out*/ + pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + thisdev; + + /*record last dev result*/ + pri->lastdev = thisdev; +#else + + if (pri->kd_enable == TRUE) + { + kd = pri->kd + self->fuzzy.kd; + } + else + { + kd = 0; + } + + pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + (error - pri->pre_error) * (kd); +#endif + + pri->pre_error = error; + /*record last feedback sensor result*/ + pri->pre_feed_back = pri->feed_back; + /*limt pid output*/ + pri->out = RANGE(pri->out, pri->out_min, pri->out_max); + return pri->out; +} +#else +#endif + +void pid_zh_constructor(struct PID_FUZZY_ZH *self) +{ + self->set_ctrl_prm = _set_ctrl_prm; + self->update_ctrl_prm = _update_ctrl_prm; + self->set_cfg = _set_cfg; + self->set_smooth_enable = _set_smooth_enable; + // self->set_ki_enable = _set_ki_enable; + self->set_kd_enable = _set_kd_enable; + self->set_range = _set_range; + self->restctrl = _restctrl; + self->PID = _PID; +} diff --git a/User/lib/control/custom/pid_zh.h b/User/lib/control/custom/pid_zh.h new file mode 100644 index 0000000..7a50129 --- /dev/null +++ b/User/lib/control/custom/pid_zh.h @@ -0,0 +1,71 @@ +#ifndef __PID_ZH_H__ +#define __PID_ZH_H__ +#include "lib.h" +#include "pid_auto_tune.h" + +typedef struct +{ + float32 ref; + float32 feed_back; + float32 pre_feed_back; + float32 pre_error; + float32 sum_ref; + float32 sum_iterm; + float32 kp; + float32 ki; + float32 kd; + float32 err_limit; + BOOL detach; + float32 err_dead; +#if INCOMPLETE_DIFFEREN == 1 + dc_t alpha; + dc_t lastdev; +#endif + float32 out; + float32 out_max; + float32 out_min; + float32 sv_range; + BOOL sm; + BOOL ki_enable; + BOOL kd_enable; +} pid_zh_position_t; // 位置式PID + +typedef struct +{ + float32 kp; + float32 ki; + float32 kd; + + float32 kup; + float32 kui; + float32 kud; +} FUZZY_PID_ZH_t; + +// 模糊PID +typedef struct PID_FUZZY_ZH +{ + /* 设置PID三个参数 */ + void (*set_ctrl_prm)(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max); // 设置PID参数 + void (*update_ctrl_prm)(struct PID_FUZZY_ZH *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max); // 更新PID参数 + void (*set_range)(struct PID_FUZZY_ZH *self, float32 out_min, float32 out_max); // 更新最大最小值 + void (*set_cfg)(struct PID_FUZZY_ZH *self, float32 max_err, BOOL mode); // 配置PID模式,默认不使用积分分离 + void (*set_smooth_enable)(struct PID_FUZZY_ZH *self, BOOL enable, float32 sv_range); // 设置平滑范围 + // void (*set_ki_enable)(struct PID_FUZZY *self, BOOL enable); + // 微分开启使能 + void (*set_kd_enable)(struct PID_FUZZY_ZH *self, BOOL enable); + void (*restctrl)(struct PID_FUZZY_ZH *self); // 复位PID积分及微分控制数据 + /* 控制接口 */ + float32 (*PID)(struct PID_FUZZY_ZH *self, float32 target, float32 feedback); + + pid_zh_position_t pri; + + BOOL open; // 是否使用模糊PID控制 + + FUZZY_PID_ZH_t fuzzy; + +} pid_zh_t; // 模糊PID + +extern void pid_zh_constructor(struct PID_FUZZY_ZH *self); +#endif diff --git a/User/lib/control/custom/独立PID算法开发.md b/User/lib/control/custom/独立PID算法开发.md new file mode 100644 index 0000000..7d32003 --- /dev/null +++ b/User/lib/control/custom/独立PID算法开发.md @@ -0,0 +1,26 @@ +# 架构 +|文件|路径|

| +|:--|:--|:--| +|pid|User\lib\control\src|PID算法模块| +|execute|User\application\src|执行器| +|app_flow|User|任务流程控制| + +## APP_FLOW任务流程控制 +> adjust_inspection 中在没有检测到调试信号时执行execute_dac,EXECUTE_PLAN定义了需要执行的算法任务计划 + +## PID算法模块 +文件内容: +|文件|
说明
| +|:--|:--| +|pid.c|构造算法的入口| +|pid_common.c|普通算法| +|pid_neural.c|神经网络算法| +|pid_fuzzy.c|模糊算法| + +custom 目录下为各自算法实现 + + +## EXECUTE执行器 +> execute_pid_init中定义了初始化参数 +> execute_dac中定义了执行器 + diff --git a/User/lib/control/inc/pid.h b/User/lib/control/inc/pid.h new file mode 100644 index 0000000..17500ae --- /dev/null +++ b/User/lib/control/inc/pid.h @@ -0,0 +1,225 @@ +#ifndef __PID_H__ +#define __PID_H__ +#include "lib.h" +#include "pid_auto_tune.h" + +#include "pid_c.h" +#include "pid_g.h" +#include "pid_x.h" +#include "pid_zh.h" +#include "pid_hd.h" + +typedef enum +{ + // PID自整定 + PID_TYPE_AUTO_TUNE, + // 通用PID + PID_TYPE_COMMON, + // 神经PID + PID_TYPE_NEURAL, + // 模糊PID + PID_TYPE_FUZZY, + + // 以下是自定义PID + + // cj PID + PID_TYPE_CUSTOM_CAO, + // gp jPID + PID_TYPE_CUSTOM_GAO, + // xsh PID + PID_TYPE_CUSTOM_XU, + // zxm PID + PID_TYPE_CUSTOM_ZHANG, + // hangdian PID + PID_TYPE_CUSTOM_HANGDIAN, +} pid_type_e; + +typedef enum +{ + // 位置式 + PID_SUB_TYPE_POSITION, + // 增量式 + PID_SUB_TYPE_INCREMENT, +} pid_sub_type_e; + +#define FUZZY_SUB_TYPE PID_SUB_TYPE_POSITION +#define INCOMPLETE_DIFFEREN 0 // 不完全微分 + +#pragma pack(1) +typedef struct +{ + float32 ref; + float32 feed_back; + float32 pre_feed_back; + float32 pre_error; + float32 sum_iterm; + float32 kp; + float32 ki; + float32 kd; + float32 err_limit; + BOOL detach; + float32 err_dead; +#if INCOMPLETE_DIFFEREN == 1 + dc_t alpha; + dc_t lastdev; +#endif + float32 out; + float32 out_max; + float32 out_min; + float32 sv_range; + BOOL sm; + BOOL ki_enable; + BOOL kd_enable; +} pid_common_position_t; // 位置式PID + +typedef struct +{ + float32 ref; // 目标设定值 + float32 feedback; // 传感器采集值 + float32 out; // PID计算结果 + float32 kp; + float32 ki; + float32 kd; + float32 e_0; // 当前误差 + float32 e_1; // 上一次误差 + float32 e_2; // 上上次误差 + float32 alpha; + float32 lastdev; + float32 err_dead; + float32 out_max; // 输出限幅 + float32 out_min; // 输出限幅 + BOOL sm; + float32 sv_range; +} pid_common_increment_t; // 增量式PID +#pragma pack() + +typedef struct PID_COMMON +{ + pid_sub_type_e type; + /* 设置PID三个参数 */ + void (*set_ctrl_prm)(struct PID_COMMON *self, float32 kp, float32 ki, float32 kd); + /* 设置积分范围 */ + void (*set_integral_prm)(struct PID_COMMON *self, float32 integral_up, float32 integral_low); + + /* 控制接口 */ + float32 (*PID)(struct PID_COMMON *self, float32 err); + + /* in value */ + float32 err; + /* out value */ + float32 out; + + union + { + pid_common_position_t position; + pid_common_increment_t increment; + } pri_u; + +} pid_common_t; // 通用PID + +typedef struct PID_NEURAL +{ + pid_sub_type_e type; + /* 设置PID三个参数 */ + void (*set_ctrl_prm)(struct PID_NEURAL *self, float32 minimum, float32 maximum); + /* 设置输出范围 */ + void (*set_out_prm)(struct PID_NEURAL *self, float32 minimum, float32 maximum); + /* 控制接口 */ + float32 (*PID)(struct PID_NEURAL *self, float32 target, float32 feedback); + + struct + { + float32 setpoint; /*设定值*/ + float32 kcoef; /*神经元输出比例*/ + float32 kp; /*比例学习速度*/ + float32 ki; /*积分学习速度*/ + float32 kd; /*微分学习速度*/ + float32 lasterror; /*前一拍偏差*/ + float32 preerror; /*前两拍偏差*/ + float32 deadband; /*死区*/ + float32 result; /*输出值*/ + float32 output; /*百分比输出值*/ + float32 maximum; /*输出值的上限*/ + float32 minimum; /*输出值的下限*/ + float32 wp; /*比例加权系数*/ + float32 wi; /*积分加权系数*/ + float32 wd; /*微分加权系数*/ + } pri; +} pid_neural_t; // 神经PID + +typedef struct +{ + float32 kp; + float32 ki; + float32 kd; + + float32 kup; + float32 kui; + float32 kud; +} FUZZY_PID_t; + +// 模糊PID +typedef struct PID_FUZZY +{ + /* 设置PID三个参数 */ + void (*set_ctrl_prm)(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max); // 设置PID参数 + void (*update_ctrl_prm)(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max); // 更新PID参数 + void (*set_range)(struct PID_FUZZY *self, float32 out_min, float32 out_max); // 更新最大最小值 + void (*set_cfg)(struct PID_FUZZY *self, float32 max_err, BOOL mode); // 配置PID模式,默认不使用积分分离 + void (*set_smooth_enable)(struct PID_FUZZY *self, BOOL enable, float32 sv_range); // 设置平滑范围 + + void (*set_err_dead)(struct PID_FUZZY *self, float32 err_dead); // 设置死区 + void (*set_kp)(struct PID_FUZZY *self, float32 kp); + void (*set_ki_enable)(struct PID_FUZZY *self, BOOL enable); + void (*set_ki)(struct PID_FUZZY *self, float32 ki); + // 微分开启使能 + void (*set_kd_enable)(struct PID_FUZZY *self, BOOL enable); + void (*set_kd)(struct PID_FUZZY *self, float32 kd); + void (*restctrl)(struct PID_FUZZY *self); // 复位PID积分及微分控制数据 + /* 控制接口 */ + float32 (*PID)(struct PID_FUZZY *self, float32 target, float32 feedback); + +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_common_position_t pri; +#else + pid_common_increment_t pri; +#endif + + BOOL open; // 是否使用模糊PID控制 + + FUZZY_PID_t fuzzy; + +} pid_fuzzy_t; // 模糊PID + +// PID +typedef struct +{ + pid_type_e type; + union + { + pid_common_t common; + pid_neural_t neural; + pid_fuzzy_t fuzzy; + + // 自定义PID + pid_c_t cao; + pid_g_t gao; + pid_x_t xu; + pid_zh_t zhang; + pid_hd_t hd; + } pid_u; + pid_auto_tune_t auto_tune; +} pid_t; + +// PID控制 +extern void pid_constructor(pid_t *self); + +// private +// 神经元PID +extern void pid_neural_constructor(struct PID_NEURAL *self); +// 模糊PID +extern void pid_fuzzy_constructor(struct PID_FUZZY *self); + +#endif diff --git a/User/lib/control/inc/pid_auto_tune.h b/User/lib/control/inc/pid_auto_tune.h new file mode 100644 index 0000000..8df274a --- /dev/null +++ b/User/lib/control/inc/pid_auto_tune.h @@ -0,0 +1,56 @@ +/*** + * @Author: + * @Date: 2023-07-24 11:17:55 + * @LastEditors: xxx + * @LastEditTime: 2023-07-24 11:19:06 + * @Description:pid自动调参,构建闭环回路 确定稳定极限 确定两个参数 极限值KP和震荡周期 + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#ifndef __PID_AUTO_TUNE_H__ +#define __PID_AUTO_TUNE_H__ +#include "lib.h" + +typedef struct PID_AUTO_TUNE +{ + // public: + void (*set_ctrl_prm)(struct PID_AUTO_TUNE *self, float32 *input, float32 *output); + int32_t (*runtime)(struct PID_AUTO_TUNE *self); + void (*set_output_step)(struct PID_AUTO_TUNE *self, int32_t step); + void (*set_control_type)(struct PID_AUTO_TUNE *self, int32_t type); + void (*set_noise_band)(struct PID_AUTO_TUNE *self, int32_t band); + void (*set_look_back)(struct PID_AUTO_TUNE *self, int32_t n); + float32 (*get_kp)(struct PID_AUTO_TUNE *self); + float32 (*get_ki)(struct PID_AUTO_TUNE *self); + float32 (*get_kd)(struct PID_AUTO_TUNE *self); + // private: + struct + { + BOOL isMax, isMin; // 运算中出现最大、最小值标志 + float32 *input, *output; + float32 setpoint; // 反向控制判断值,这个值需要根据对象的实际工作值确定!是通过第一次启动时对应的输入值带入的。 + int32_t noiseBand; // 判断回差,类似于施密特触发器,实际控制反向的比较值是 setpoint + noiseBand 或 setpoint - noiseBand + int32_t controlType; // 计算 PID 参数时,选择 PI 或 PID 模式,输出 Kp Ki,或 Kp、Ki、Kd + BOOL running; + uint32_t peak1, peak2, lastTime; // 峰值对应的时间 + int32_t sampleTime; + int32_t nLookBack; + int32_t peakType; + // double lastInputs[101]; // 保存的历史输入值, 最多存前 100 次 + int32_t lastInputs[51]; // 保存的历史输入值, 改为 50 次。 by shenghao.xu + int32_t peaks[13]; // 保存的历史峰值,最多存前 12 次,对应 6个最大、6个最小。20221124 by Embedream + int32_t peakCount; // 峰值计数 + int32_t peakPeriod[7]; // 保存前 6 次的最大值间隔时间 by shenghao.xu + int32_t peakMaxCount; // 最大峰值计数 by shenghao.xu + BOOL justchanged; + // BOOL justevaled; // 此标志没有使用 + // int32_t absMax, absMin; // 整个过程中采集的输入最大值、最小值 + int32_t oStep; // 这个值是用于计算控制高低值的,以 outputStart 为中值,输出高值用 outputStart + oStep, 输出低值用 outputStart - oStep + float32 outputStart; // 输出控制的基础值,这个需要结合对象特征确定,此值也是通过第一次启动时对应的输出值带入的。 + float32 Ku, Pu; + } pri; + +} pid_auto_tune_t; + +extern void pid_auto_tune_constructor(struct PID_AUTO_TUNE *self); +#endif // __PID_AUTO_TUNE_H__ diff --git a/User/lib/control/src/pid.c b/User/lib/control/src/pid.c new file mode 100644 index 0000000..f0a1f76 --- /dev/null +++ b/User/lib/control/src/pid.c @@ -0,0 +1,39 @@ +#include "pid.h" +#include + +// 构造函数将接口绑定 +void pid_constructor(pid_t *self) +{ + switch (self->type) + { + case PID_TYPE_COMMON: + /* code */ + break; + case PID_TYPE_NEURAL: + pid_neural_constructor(&self->pid_u.neural); + break; + case PID_TYPE_FUZZY: + pid_fuzzy_constructor(&self->pid_u.fuzzy); + break; + case PID_TYPE_AUTO_TUNE: + pid_auto_tune_constructor(&self->auto_tune); + break; + case PID_TYPE_CUSTOM_CAO: + pid_c_constructor(&self->pid_u.cao); + break; + case PID_TYPE_CUSTOM_GAO: + pid_g_constructor(&self->pid_u.gao); + break; + case PID_TYPE_CUSTOM_XU: + pid_x_constructor(&self->pid_u.xu); + break; + case PID_TYPE_CUSTOM_ZHANG: + pid_zh_constructor(&self->pid_u.zhang); + break; + case PID_TYPE_CUSTOM_HANGDIAN: + pid_hd_constructor(&self->pid_u.hd); + break; + default: + break; + } +} diff --git a/User/lib/control/src/pid_auto_tune.c b/User/lib/control/src/pid_auto_tune.c new file mode 100644 index 0000000..d3dee1b --- /dev/null +++ b/User/lib/control/src/pid_auto_tune.c @@ -0,0 +1,230 @@ +#include "pid_auto_tune.h" +#include "sys.h" + +/* + 设置峰值回溯时间,单位 0.1 秒,最小 0.2秒, 最大 4 秒 +*/ +static void set_look_backsec(pid_auto_tune_t *self, int32_t value) +{ + if (value < 2) + value = 2; + if (value > 40) + value = 40; + + if (value < 40) + { + self->pri.nLookBack = 12; // 按目前实际周期约300ms、采样周期 10ms 考虑,一个周期只有 30 点,回溯 12 点即可。 + self->pri.sampleTime = value * 10; // 改为 Value*100 ms, 20、30、40 ~ 200ms + } + else + { + self->pri.nLookBack = 50 + value; + self->pri.sampleTime = 4000; + } +} + +static void _set_ctrl_prm(struct PID_AUTO_TUNE *self, float32 *input, float32 *output) +{ + self->pri.input = input; + self->pri.output = output; + self->pri.controlType = 0; // 默认为 PI 模式 + self->pri.noiseBand = 1; + self->pri.running = FALSE; + self->pri.oStep = 1; + set_look_backsec(self, 1); + self->pri.lastTime = sys_millis(); +} + +static void _set_noise_band(struct PID_AUTO_TUNE *self, int32_t value) +{ + self->pri.noiseBand = value; +} + +static void _set_output_step(struct PID_AUTO_TUNE *self, int32_t value) +{ + self->pri.oStep = value; +} + +// * Determies if the tuning parameters returned will be PI (D=0) +// or PID. (0=PI, 1=PID) +static void _set_control_type(struct PID_AUTO_TUNE *self, int32_t value) +{ + self->pri.controlType = value; +} + +static void _set_look_back(struct PID_AUTO_TUNE *self, int32_t value) +{ + set_look_backsec(self, value); +} + +static float32 _get_kp(struct PID_AUTO_TUNE *self) +{ + float32 kp = self->pri.controlType == 1 ? 0.6f * self->pri.Ku : 0.4f * self->pri.Ku; + return kp; +} + +static float32 _get_ki(struct PID_AUTO_TUNE *self) +{ + float32 ki = self->pri.controlType == 1 ? 1.2f * self->pri.Ku / self->pri.Pu : 0.48f * self->pri.Ku / self->pri.Pu; + return ki; +} + +static float32 _get_kd(struct PID_AUTO_TUNE *self) +{ + return self->pri.controlType == 1 ? 0.075f * self->pri.Ku * self->pri.Pu : 0; +} + +/** + * @brief 修改返回值,0 - 执行计算,未完成整定, 1 - 执行计算,完成整定过程, 2 - 采样时间未到 + * @return {*} + */ +static int32_t _runtime(struct PID_AUTO_TUNE *self) +{ + int32_t i, iSum; + + uint32_t now = sys_millis(); + if ((now - self->pri.lastTime) < ((uint32_t)self->pri.sampleTime)) + { + return 2; // 原来返回值为 FALSE 不符合函数定义,也无法区分,改为 2,by shenghao.xu + } + + // 开始整定计算 + self->pri.lastTime = now; + float32 refVal = *(self->pri.input); + if (FALSE == self->pri.running) // 首次进入,初始化参数 + { + self->pri.peakType = 0; + self->pri.peakCount = 0; + self->pri.peakMaxCount = 0; + self->pri.peak1 = 0; + self->pri.peak2 = 0; + self->pri.justchanged = FALSE; + self->pri.setpoint = refVal; // 不变 + self->pri.running = TRUE; + self->pri.outputStart = *self->pri.output; + *self->pri.output = self->pri.outputStart + self->pri.oStep; + } + + // 根据输入与设定点的关系振荡输出 + if (refVal > (self->pri.setpoint + self->pri.noiseBand)) + *self->pri.output = self->pri.outputStart - self->pri.oStep; + else if (refVal < (self->pri.setpoint - self->pri.noiseBand)) + *self->pri.output = self->pri.outputStart + self->pri.oStep; + + // bool isMax=TRUE, isMin=TRUE; + self->pri.isMax = TRUE; + self->pri.isMin = TRUE; + // id peaks + /* + 以下循环完成,对回溯次数的输入缓存进行判断,如果输入值均大于或小于缓存值,则确定此次为峰值。 + 峰值特征根据 isMax、isMin 哪个为真确定。 + 同时完成输入缓存向后平移,腾出第一个单元存放新的输入值。 + 这一段代码完成的噪声所产生的虚假峰值判断,应该没有问题! + */ + for (i = self->pri.nLookBack - 1; i >= 0; i--) + { + int32_t val = self->pri.lastInputs[i]; + if (self->pri.isMax) + self->pri.isMax = (refVal > val); // 第一次是新输入和缓存最后一个值比较,如果大于,则前面的值均判是否大于 + if (self->pri.isMin) + self->pri.isMin = (refVal < val); // 第一次是新输入和缓存最后一个值比较,如果小于,则前面的值均判是否小于 + self->pri.lastInputs[i + 1] = self->pri.lastInputs[i]; // 每采样一次,将输入缓存的数据向后挪一次 + } + self->pri.lastInputs[0] = refVal; // 新采样的数据放置缓存第一个单元。 + + /* + 以下代码完成峰值的确定,以及对应峰值的时间纪录。 + 因为上述代码只是去掉噪产生的波动峰值,但如果是连续超过 nLookBack 次数的的上升或下降, + 则上述算法所确定的最大或最小值,并非是峰值,只能是前 nLookBack 次中的最大或最小值。 + 但逐句消化程序后,发现这段处理有几点疑惑: + 1、peaks[] 的纪录好像不对,在执行最小到最大值转换时,peakCount 也应该+1,否则应该把 + 纪录的最小值覆盖了!所以后面的峰值判断总是满足条件。 + 2、峰值对应时间似乎也应该多次存放,取平均值,因对象没有那么理想化,目前应该是取的最后一组峰值的周期。 + 3、后续计算 Ku 用的是整个整定过程的最大、最小值,这对于非理想的对象而言也不是很合适。 + + 考虑做如下改进: + 1)修改峰值纪录,设计12个峰值保存单元,存满12个峰值(6大、6小)后再计算。 + 2)纪录 6 组最大值的间隔时间,作为最终计算 Pu 的数据。 + */ + if (self->pri.isMax) + { + if (self->pri.peakType == 0) + self->pri.peakType = 1; // 首次最大值,初始化 + + if (self->pri.peakType == -1) // 如果前一次为最小值,则标识目前进入最大值判断 + { + self->pri.peakType = 1; // 开始最大值判断 + self->pri.peakCount++; // 峰值计数 by shenghao.xu + self->pri.justchanged = TRUE; // 标识峰值转换 + if (self->pri.peak2 != 0) // 已经纪录一次最大峰值对应时间后,开始记录峰值周期 by shenghao.xu + { + self->pri.peakPeriod[self->pri.peakMaxCount] = (int32_t)(self->pri.peak1 - self->pri.peak2); // 最大峰值间隔时间(即峰值周期) + self->pri.peakMaxCount++; // 最大峰值计数 + } + self->pri.peak2 = self->pri.peak1; // 刷新上次最大值对应时间 + } + self->pri.peak1 = now; // 保存最大值对应时间 peak1 + self->pri.peaks[self->pri.peakCount] = refVal; // 保存最大值 + } // 此段代码可以保证得到的是真正的最大值,因为peakType不变,则会不断刷新最大值 + else if (self->pri.isMin) + { + if (self->pri.peakType == 0) + self->pri.peakType = -1; // 首次最小值,初始化 + + if (self->pri.peakType == 1) // 如果前一次是最大值判断,则转入最小值判断 + { + self->pri.peakType = -1; // 开始最小值判断 + self->pri.peakCount++; // 峰值计数 + self->pri.justchanged = TRUE; + } + + if (self->pri.peakCount < 10) + self->pri.peaks[self->pri.peakCount] = refVal; // 只要类型不变,就不断刷新最小值 + } + + /* by shenghao.xu + 以下计算是作为判断采集数据是否合适的部分,如果 2 次峰值判断条件满足,就结束整定过程,感觉不甚合理。 + 拟修改为: + 1)计满 12 次峰值后再计算(到第 13 次)。 + 2)不再判断是否合理,因为对象如果特性好,自然已经稳定,如果不好,再长时间也无效果。 + 3)将后面5次的数据作为素材,去掉第一组数据,因为考虑第一组时对象可能处于过渡过程。 + 4)用后 10 点得到的 9 个峰值差平均值作为 Ku 计算值中的 A,取代原来的整个过程的最大、最小值差。 + 5)用后 5 点峰值周期平均值作为 Pu 的计算值,取代原来用最后一组的值。 + */ + if (self->pri.justchanged && self->pri.peakCount == 12) + { + // we've transitioned. check if we can autotune based on the last peaks + iSum = 0; + for (i = 2; i <= 10; i++) + iSum += ABS(self->pri.peaks[i] - self->pri.peaks[i + 1]); + iSum /= 9; // 取 9 次峰峰值平均值 + self->pri.Ku = (float32)(4 * (2 * self->pri.oStep)) / (iSum * 3.14159); // 用峰峰平均值计算 Ku + + iSum = 0; + for (i = 1; i <= 5; i++) + iSum += self->pri.peakPeriod[i]; + iSum /= 5; // 计算峰值的所有周期平均值 + self->pri.Pu = (float32)(iSum) / 1000; // 用周期平均值作为 Pu,单位:秒 + + *self->pri.output = 0; + self->pri.running = FALSE; + return 1; + } + + self->pri.justchanged = FALSE; + return 0; +} + +void pid_auto_tune_constructor(struct PID_AUTO_TUNE *self) +{ + self->set_ctrl_prm = _set_ctrl_prm; + self->runtime = _runtime; + self->set_output_step = _set_output_step; + self->set_control_type = _set_control_type; + self->set_noise_band = _set_noise_band; + self->set_look_back = _set_look_back; + + self->get_kp = _get_kp; + self->get_ki = _get_ki; + self->get_kd = _get_kd; +} diff --git a/User/lib/control/src/pid_common.c b/User/lib/control/src/pid_common.c new file mode 100644 index 0000000..e69de29 diff --git a/User/lib/control/src/pid_fuzzy.c b/User/lib/control/src/pid_fuzzy.c new file mode 100644 index 0000000..3ef736e --- /dev/null +++ b/User/lib/control/src/pid_fuzzy.c @@ -0,0 +1,519 @@ +#include "pid.h" +#include + +// 模糊集合 +#define NL -3 +#define NM -2 +#define NS -1 +#define ZE 0 +#define PS 1 +#define PM 2 +#define PL 3 + +// 定义偏差E的范围,因为设置了非线性区间,误差在10时才开始进行PID调节,这里E的范围为10 +#define MAXE (10) +#define MINE (-MAXE) +// 定义EC的范围,因为变化非常缓慢!,每次的EC都非常小,这里可以根据实际需求来调整, +#define MAXEC (10) +#define MINEC (-MAXEC) +// 定义e,ec的量化因子 +#define KE 3 / MAXE +#define KEC 3 / MAXEC + +// 定义输出量比例因子 +#define KUP 3.0f // 这里只使用了模糊PID的比例增益 +#define KUI 0.0f +#define KUD 3.0f + +static const float32 fuzzyRuleKp[7][7] = { + PL, PL, PM, PL, PS, PM, PL, + PL, PM, PM, PM, PS, PM, PL, + PM, PS, PS, PS, PS, PS, PM, + PM, PS, ZE, ZE, ZE, PS, PM, + PS, PS, PS, PS, PS, PM, PM, + PM, PM, PM, PM, PL, PL, PL, + PM, PL, PL, PL, PL, PL, PL}; + +static const float32 fuzzyRuleKi[7][7] = { + NL, NL, NL, NL, NM, NL, NL, + NL, NL, NM, NM, NM, NL, NL, + NM, NM, NS, NS, NS, NM, NM, + NM, NS, ZE, ZE, ZE, NS, NM, + NM, NS, NS, NS, NS, NM, NM, + NM, NM, NS, NM, NM, NL, NL, + NM, NL, NM, NL, NL, NL, NL}; + +static const float32 fuzzyRuleKd[7][7] = { + PS, PS, ZE, ZE, ZE, PL, PL, + NS, NS, NS, NS, ZE, NS, PM, + NL, NL, NM, NS, ZE, PS, PM, + NL, NM, NM, NS, ZE, PS, PM, + NL, NM, NS, NS, ZE, PS, PS, + NM, NS, NS, NS, ZE, PS, PS, + PS, ZE, ZE, ZE, ZE, PL, PL}; + +static void fuzzy(float32 e, float32 ec, FUZZY_PID_t *fuzzy_pid) +{ + + float32 etemp, ectemp; + float32 eLefttemp, ecLefttemp; // ec,e,左隶属度 + float32 eRighttemp, ecRighttemp; + + int eLeftIndex, ecLeftIndex; // 模糊位置标号 + int eRightIndex, ecRightIndex; + e = RANGE(e, MINE, MAXE); + ec = RANGE(ec, MINEC, MAXEC); + e = e * KE; + ec = ec * KEC; + + etemp = e > 3.0f ? 0.0f : (e < -3.0f ? 0.0f : (e >= 0.0f ? (e >= 2.0f ? 2.5f : (e >= 1.0f ? 1.5f : 0.5f)) : (e >= -1.0f ? -0.5f : (e >= -2.0f ? -1.5f : (e >= -3.0f ? -2.5f : 0.0f))))); + eLeftIndex = (int)((etemp - 0.5f) + 3); //[-3,3] -> [0,6] + eRightIndex = (int)((etemp + 0.5f) + 3); + eLefttemp = etemp == 0.0f ? 0.0f : ((etemp + 0.5f) - e); // + eRighttemp = etemp == 0.0f ? 0.0f : (e - (etemp - 0.5f)); + ectemp = ec > 3.0f ? 0.0f : (ec < -3.0f ? 0.0f : (ec >= 0.0f ? (ec >= 2.0f ? 2.5f : (ec >= 1.0f ? 1.5f : 0.5f)) : (ec >= -1.0f ? -0.5f : (ec >= -2.0f ? -1.5f : (ec >= -3.0f ? -2.5f : 0.0f))))); + ecLeftIndex = (int)((ectemp - 0.5f) + 3); //[-3,3] -> [0,6] + ecRightIndex = (int)((ectemp + 0.5f) + 3); + + ecLefttemp = ectemp == 0.0f ? 0.0f : ((ectemp + 0.5f) - ec); + ecRighttemp = ectemp == 0.0f ? 0.0f : (ec - (ectemp - 0.5f)); + + /*************************************反模糊*************************************/ + + fuzzy_pid->kp = (eLefttemp * ecLefttemp * fuzzyRuleKp[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKp[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKp[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKp[eRightIndex][ecRightIndex]); + + fuzzy_pid->ki = (eLefttemp * ecLefttemp * fuzzyRuleKi[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKi[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKi[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKi[eRightIndex][ecRightIndex]); + + fuzzy_pid->kd = (eLefttemp * ecLefttemp * fuzzyRuleKd[eLeftIndex][ecLeftIndex] + eLefttemp * ecRighttemp * fuzzyRuleKd[eLeftIndex][ecRightIndex] + eRighttemp * ecLefttemp * fuzzyRuleKd[eRightIndex][ecLeftIndex] + eRighttemp * ecRighttemp * fuzzyRuleKd[eRightIndex][ecRightIndex]); + // 对解算出的KP,KI,KD进行量化映射 + + fuzzy_pid->kp = fuzzy_pid->kp * fuzzy_pid->kup; + fuzzy_pid->ki = fuzzy_pid->ki * fuzzy_pid->kui; + fuzzy_pid->kd = fuzzy_pid->kd * fuzzy_pid->kud; +} + +/** + * @brief SV平滑给定,步长默认为0.1,范围0-1之间,越大平滑性越差 + * @param {PID_FUZZY} *self + * @param {float32} target_sv + * @return {*} + * @note + */ +static void smoothSetpoint(struct PID_FUZZY *self, float32 target_sv) +{ +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_common_position_t *pri = &self->pri; +#else + pid_common_increment_t *pri = &self->pri; +#endif + float32 stepIn = (pri->sv_range) * 0.1f; + float32 kFactor = 0.0f; + if (fabs(pri->ref - target_sv) <= stepIn) + { + pri->ref = target_sv; + } + else + { + if (pri->ref - target_sv > 0) + { + kFactor = -1.0f; + } + else if (pri->ref - target_sv < 0) + { + kFactor = 1.0f; + } + else + { + kFactor = 0.0f; + } + pri->ref = pri->ref + kFactor * stepIn; + } +} + +/*封装模糊接口*/ +static void compensate(float32 e, float32 ec, FUZZY_PID_t *fuzzy_d) +{ + fuzzy(e, ec, fuzzy_d); +} + +/** + * @brief 更新最大最小值 + * @param {PID_FUZZY} *self + * @param {float32} out_min + * @param {float32} out_max + * @return {*} + * @note + */ +static void _set_range(struct PID_FUZZY *self, float32 out_min, float32 out_max) +{ + self->pri.out_max = out_max; + self->pri.out_min = out_min; +} + +/** + * @brief 设置死区 + * @param {PID_FUZZY} *self + * @param {float32} err_dead + * @return {*} + * @note + */ +static void _set_err_dead(struct PID_FUZZY *self, float32 err_dead) +{ + self->pri.err_dead = err_dead; +} + +static void _set_kp(struct PID_FUZZY *self, float32 kp) +{ + self->pri.kp = kp; +} + +/** + * @brief 使能积分控制 + * @param {PID_FUZZY} *self + * @param {BOOL} enable + * @return {*} + * @note + */ +// static void _set_ki_enable(struct PID_FUZZY *self, BOOL enable) +// { +// self->pri.ki_enable = enable; +// } + +/** + * @brief 使能微分控制 + * @param {PID_FUZZY} *self + * @param {BOOL} enable + * @return {*} + * @note + */ +static void _set_kd_enable(struct PID_FUZZY *self, BOOL enable) +{ + self->pri.kd_enable = enable; +} + +static void _set_kd(struct PID_FUZZY *self, float32 kd) +{ + self->pri.kd = kd; +} + +static void _set_ki_enable(struct PID_FUZZY *self, BOOL enable) +{ + self->pri.ki_enable = enable; +} + +static void _set_ki(struct PID_FUZZY *self, float32 ki) +{ + self->pri.ki = ki; +} + +/* + * Function:使能平滑控制 + * parameter:*pid需要配,PID参数结构指针,sv_range控制范围sv的范围 + * return:无 + */ +static void _set_smooth_enable(struct PID_FUZZY *self, BOOL enable, float32 sv_range) +{ +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_common_position_t *pri = &self->pri; +#else + pid_common_increment_t *pri = &self->pri; +#endif + pri->sm = enable; + pri->sv_range = sv_range; +} + +// 设置控制参数 +static void _set_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max) +{ + self->open = TRUE; + self->fuzzy.kup = KUP; + self->fuzzy.kui = KUI; + self->fuzzy.kud = KUD; +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_common_position_t *pri = &self->pri; + osel_memset((uint8_t *)pri, 0, sizeof(pid_common_position_t)); + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; + pri->detach = FALSE; + pri->sm = FALSE; +#else + pid_common_increment_t *pri = &self->pri; + osel_memset((uint8_t *)pri, 0, sizeof(pid_common_increment_t)); + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; +#endif + pri->ki_enable = TRUE; +} + +static void _update_ctrl_prm(struct PID_FUZZY *self, float32 kp, float32 ki, float32 kd, float32 err_dead, + float32 out_min, float32 out_max) +{ +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION + pid_common_position_t *pri = &self->pri; + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; + pri->detach = FALSE; + pri->sm = FALSE; +#else + pid_common_increment_t *pri = &self->pri; + pri->kp = kp; + pri->ki = ki; + pri->kd = kd; + pri->err_dead = err_dead; + pri->out_max = out_max; + pri->out_min = out_min; +#endif + + if (kd > 0) + { + pri->kd_enable = TRUE; + } + else + { + pri->kd_enable = FALSE; + } +} + +/** + * @brief 非0时配置为积分分离+抗积分饱和PID,否则为普通抗积分饱和PID + * @param {PID_FUZZY} *self + * @param {float32} max_err + * @param {BOOL} mode + * @return {*} + */ +static void _set_cfg(struct PID_FUZZY *self, float32 max_err, BOOL mode) +{ + self->pri.err_limit = max_err; + self->pri.detach = mode == FALSE ? FALSE : TRUE; +} + +#if FUZZY_SUB_TYPE == PID_SUB_TYPE_POSITION +static float32 _PID(struct PID_FUZZY *self, float32 target, float32 feedback) +{ + float32 error = 0; + float32 insert = 0; + float32 ec = 0; + float32 kd = 0; +#if INCOMPLETE_DIFFEREN == 1 + float32 thisdev = 0; +#else + // float32 dinput = 0.0f; +#endif + // float32 fuzzy_kp = 0.0f; + // float32 fuzzy_ki = 0.0f; + // float32 fuzzy_kd = 0.0f; + float32 temp_iterm = 0.0f; + pid_common_position_t *pri = &self->pri; + + /*获取期望值与实际值,进行偏差计算*/ + if (pri->sm == 1) + { + smoothSetpoint(self, target); + } + else + { + pri->ref = target; + } + + pri->feed_back = feedback; + error = pri->ref - pri->feed_back; + if (fabs(error) <= pri->err_dead) + error = 0; + + /* fuzzy control caculate */ + ec = error - pri->pre_error; + if (self->open == TRUE) + { + compensate(error, ec, &self->fuzzy); + } + + /*根据PID配置的模式,获取积分数据,进行积分累加*/ + if (pri->out >= pri->out_max) + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + if (error < 0) + { + temp_iterm = (pri->ki + self->fuzzy.ki) * error; + } + } + } + else if (pri->out <= pri->out_min) + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + if (error > 0) + { + temp_iterm = (pri->ki + self->fuzzy.ki) * error; + } + } + } + else + { + if (fabs(error) > pri->err_limit && pri->detach) + { + insert = 0; + } + else + { + insert = 1; + temp_iterm = (pri->ki + self->fuzzy.ki) * error; + } + } + + pri->sum_iterm += temp_iterm; + /* limt integral */ + if (pri->sum_iterm > pri->out_max) + { + pri->sum_iterm = pri->out_max; + } + else if (pri->sum_iterm < pri->out_min) + { + pri->sum_iterm = pri->out_min; + } + +#if INCOMPLETE_DIFFEREN == 1 + /*不完全微分*/ + thisdev = (pri->kd + self->fuzzy.kd) * (1.0 - pri->alpha) * (error - pri->pre_error) + pri->alpha * pri->lastdev; + /*caculate pid out*/ + pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + thisdev; + + /*record last dev result*/ + pri->lastdev = thisdev; +#else + + if (pri->kd_enable == TRUE) + { + kd = pri->kd + self->fuzzy.kd; + } + else + { + kd = 0; + } + + if (pri->ki_enable == FALSE) + { + insert = 0; + } + + pri->out = (pri->kp + self->fuzzy.kp) * error + pri->sum_iterm * insert + (error - pri->pre_error) * (kd); +#endif + + pri->pre_error = error; + /*record last feedback sensor result*/ + pri->pre_feed_back = pri->feed_back; + /*limt pid output*/ + pri->out = RANGE(pri->out, pri->out_min, pri->out_max); + return pri->out; +} + +/** + * @brief 复位PID积分及微分控制数据 + * @param {PID_FUZZY} *self + * @return {*} + */ +static void _restctrl(struct PID_FUZZY *self) +{ + self->pri.pre_error = 0; + self->pri.sum_iterm = 0; +#if INCOMPLETE_DIFFEREN == 1 + self->pri.lastdev = 0; +#endif +} + +#elif FUZZY_SUB_TYPE == PID_SUB_TYPE_INCREMENT +static float32 _PID(struct PID_FUZZY *self, float32 target, float32 feedback) +{ + float fuzzy_kp = 0.0f; + float fuzzy_ki = 0.0f; + float fuzzy_kd = 0.0f; + + dc_t ep, ei, ed; + dc_t inc_out; + dc_t thisdev = 0; + if (pri->sm == 1) + { + smoothSetpoint(self, target); + } + else + { + pri->ref = target; + } + pri->feedback = feedback; + pri->e_0 = pri->ref - pri->feedback; + if (fabs(pri->e_0) <= pri->err_dead) + pri->e_0 = 0; + ep = pri->e_0 - pri->e_1; + ei = pri->e_0; + ed = pri->e_0 - 2 * pri->e_1 + pri->e_2; + if (self->open == TRUE) + { + compensate(pri->e_0, ep, &self->fuzzy); + } + /*不完全微分*/ + thisdev = (1.0 - pri->alpha) * (pri->kd + fuzzy_kd) * ed + pri->alpha * pri->lastdev; + inc_out = (pri->kp + fuzzy_kp) * ep + (pri->ki + fuzzy_ki) * ei + thisdev; + pri->e_2 = pri->e_1; + pri->e_1 = pri->e_0; + pri->lastdev = thisdev; + // pri->out = pri->out + inc_out; + pri->out = inc_out; + pri->out = RANGE(pri->out, pri->out_min, pri->out_max); + return pri->out; +} + +/** + * @brief 复位PID积分及微分控制数据 + * @param {PID_FUZZY} *self + * @return {*} + */ +static void _restctrl(struct PID_FUZZY *self) +{ + self->e_0 = 0; + self->e_1 = 0; + self->e_2 = 0; + self->lastdev = 0; +} +#else +#error Please Define PID Controller Type +#endif + +void pid_fuzzy_constructor(struct PID_FUZZY *self) +{ + self->set_ctrl_prm = _set_ctrl_prm; + self->update_ctrl_prm = _update_ctrl_prm; + self->set_cfg = _set_cfg; + self->set_smooth_enable = _set_smooth_enable; + self->set_err_dead = _set_err_dead; + self->set_kp = _set_kp; + self->set_ki_enable = _set_ki_enable; + self->set_ki = _set_ki; + self->set_kd_enable = _set_kd_enable; + self->set_kd = _set_kd; + self->set_range = _set_range; + self->restctrl = _restctrl; + self->PID = _PID; +} diff --git a/User/lib/control/src/pid_neural.c b/User/lib/control/src/pid_neural.c new file mode 100644 index 0000000..f7991c4 --- /dev/null +++ b/User/lib/control/src/pid_neural.c @@ -0,0 +1,97 @@ +#include "pid.h" +#include +// 设置控制参数 +static void _set_ctrl_prm(struct PID_NEURAL *self, float32 minimum, float32 maximum) +{ + self->pri.setpoint = minimum; /*设定值*/ + + self->pri.kcoef = 0.12; /*神经元输出比例*/ + self->pri.kp = 0.45; /*比例学习速度*/ + self->pri.ki = 0.05; /*积分学习速度*/ + self->pri.kd = 0; /*微分学习速度*/ + + self->pri.lasterror = 0.0; /*前一拍偏差*/ + self->pri.preerror = 0.0; /*前两拍偏差*/ + self->pri.result = minimum; /*PID控制器结果*/ + self->pri.output = 0.0; /*输出值,百分比*/ + + self->pri.maximum = maximum; /*输出值上限*/ + self->pri.minimum = minimum; /*输出值下限*/ + self->pri.deadband = (maximum - minimum) * 0.0005; /*死区*/ + + self->pri.wp = 0.10; /*比例加权系数*/ + self->pri.wi = 0.10; /*积分加权系数*/ + self->pri.wd = 0.10; /*微分加权系数*/ +} + +// 设置输出参数 +static void _set_out_prm(struct PID_NEURAL *self, float32 minimum, float32 maximum) +{ + self->pri.maximum = maximum; + self->pri.minimum = minimum; +} + +/*单神经元学习规则函数*/ +static void NeureLearningRules(struct PID_NEURAL *self, float32 zk, float32 uk, float32 *xi) +{ + self->pri.wi = self->pri.wi + self->pri.ki * zk * uk * xi[0]; + self->pri.wp = self->pri.wp + self->pri.kp * zk * uk * xi[1]; + self->pri.wd = self->pri.wd + self->pri.kd * zk * uk * xi[2]; +} + +static float32 _PID(struct PID_NEURAL *self, float32 target, float32 feedback) +{ + float32 x[3]; + float32 w[3]; + float32 sabs; + float32 error; + float32 result; + float32 deltaResult; + self->pri.setpoint = target; + error = self->pri.setpoint - feedback; + result = self->pri.result; + if (fabs(error) > self->pri.deadband) + { + x[0] = error; + x[1] = error - self->pri.lasterror; + x[2] = error - self->pri.lasterror * 2 + self->pri.preerror; + + sabs = fabs(self->pri.wi) + fabs(self->pri.wp) + fabs(self->pri.wd); + w[0] = self->pri.wi / sabs; + w[1] = self->pri.wp / sabs; + w[2] = self->pri.wd / sabs; + + deltaResult = (w[0] * x[0] + w[1] * x[1] + w[2] * x[2]) * self->pri.kcoef; + } + else + { + deltaResult = 0; + } + + result = result + deltaResult; + if (result > self->pri.maximum) + { + result = self->pri.maximum; + } + if (result < self->pri.minimum) + { + result = self->pri.minimum; + } + self->pri.result = result; + self->pri.output = self->pri.result; + + // 单神经元学习 + NeureLearningRules(self, error, result, x); + + self->pri.preerror = self->pri.lasterror; + self->pri.lasterror = error; + + return self->pri.output; +} + +void pid_neural_constructor(struct PID_NEURAL *self) +{ + self->set_ctrl_prm = _set_ctrl_prm; + self->set_out_prm = _set_out_prm; + self->PID = _PID; +} diff --git a/User/lib/control/自整定.md b/User/lib/control/自整定.md new file mode 100644 index 0000000..74ed869 --- /dev/null +++ b/User/lib/control/自整定.md @@ -0,0 +1 @@ +https://www.cnblogs.com/foxclever/p/16299063.html diff --git a/User/lib/examples/Makefile b/User/lib/examples/Makefile new file mode 100644 index 0000000..ac0de08 --- /dev/null +++ b/User/lib/examples/Makefile @@ -0,0 +1,86 @@ +# 变量BIN: 给定的是我们想要生成的可执行文件的名称 +BIN = run.exe +SO = lib.dll + +# 变量SRC中给的是所有的想要编译的.c源文件,与makefile在同一目录下可直接写(如这里的main.c),否则需要写明相对路径(如这里的其余源文件都在目录src下)。 +# 多文件时,选择用"\"进行分行处理 +SRC = \ + ../src/malloc.c \ + ../src/sqqueue.c \ + ../src/mlist.c \ + ../src/debug.c \ + ../src/data_analysis.c \ + ../src/filter.c \ + ../src/clist.c \ + ../src/aes.c \ + ../src/cmac.c \ + ../src/lib.c + +EXAMPLE = \ + ./simple_clist.c \ + ./simple_data_analysis.c \ + ./simple_sqqueue.c \ + ./simple_aes.c \ + ./simple_cmac.c + +CPLUS_INCLUDE_PATH= -I ../inc + +# 变量CC:给定编译器名gcc +# 变量CFLAGS:传给编译器的某些编译参数,看需求添加 +CC = gcc +CFLAGS = -m32 -std=c99 +# 变量GDB:给定debugger名gdb +# 变量RM:给定删除文件方式,用于后面删除所有编译所得的.o文件,linux下使用rm -rf +GDB = gdb +RM = rm -rf +# 变量OBJS:将变量SRC中所有的.c文件替换成以.o结尾,即将.c源文件编译成.o文件 +OBJS = $(SRC:%.c=%.o) +EXAPMLES = $(EXAMPLE:%.c=%.o) + +$(SO): $(OBJS) $(EXAPMLES) + + +# pull in dependencies for .o files +-include $(OBJS:.o=.d) + +%.o: %.c + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) -c $< -o $@ + +.PHONY: all clean clist data_analysis + +all: $(SO) + +rm: + $(RM) $(OBJS) + +#简单链表 +clist: $(SO) + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) $(OBJS) ./simple_clist.o -o $(BIN) + $(RM) $(OBJS) $(EXAPMLES) + +#数据分析器 +data_analysis: $(SO) + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) $(OBJS) ./simple_data_analysis.o -o $(BIN) + $(RM) $(OBJS) $(EXAPMLES) + +#队列 +sqqueue: $(SO) + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) $(OBJS) ./simple_sqqueue.o -o $(BIN) + $(RM) $(OBJS) $(EXAPMLES) + +#aes加密 +aes: $(SO) + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) $(OBJS) ./simple_aes.o -o $(BIN) + $(RM) $(OBJS) $(EXAPMLES) + +#cmac类CRC +cmac: $(SO) + $(CC) $(CPLUS_INCLUDE_PATH) $(CFLAGS) $(OBJS) ./simple_cmac.o -o $(BIN) + $(RM) $(OBJS) $(EXAPMLES) + +#运行程序 +run: + ./run.exe + +clean: + $(RM) $(OBJS) $(EXAPMLES) $(BIN) diff --git a/User/lib/examples/simple_aes.c b/User/lib/examples/simple_aes.c new file mode 100644 index 0000000..fb4fd5c --- /dev/null +++ b/User/lib/examples/simple_aes.c @@ -0,0 +1,40 @@ +#include "../inc/data_type_def.h" +#include "../inc/log.h" +#include "../inc/osel_arch.h" +#include "../inc/aes.h" + +// 全局变量 +static aes_context AesContext; // 密钥表 +static uint8_t aBlock[] = {0x00, 0x00, 0x00, 0xcc, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 数据块 +static uint8_t sBlock[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 存放输出结果 + +int32_t main(void) +{ + uint8_t buf[16] = {0x00}; + uint8_t size = ARRAY_LEN(buf); + uint8_t key[] = { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥 + + // 初始化密文 + for (int i = 0; i < size; i++) + { + buf[i] = i; + } + + // 设置预密钥 + osel_memset(AesContext.ksch, 0, ARRAY_LEN(AesContext.ksch)); + aes_set_key(key, 16, &AesContext); + + // 加密 + osel_memcpy(aBlock, buf, size); + aes_encrypt(aBlock, sBlock, &AesContext); + LOG_HEX(sBlock, ARRAY_LEN(sBlock)); // 打印加密结果:50 fe 67 cc 99 6d 32 b6 da 09 37 e9 9b af ec 60 + + // 解密 + osel_memcpy(aBlock, sBlock, size); + aes_decrypt(aBlock, sBlock, &AesContext); + LOG_HEX(sBlock, ARRAY_LEN(sBlock)); // 打印解密结果:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +} diff --git a/User/lib/examples/simple_clist.c b/User/lib/examples/simple_clist.c new file mode 100644 index 0000000..3254b07 --- /dev/null +++ b/User/lib/examples/simple_clist.c @@ -0,0 +1,52 @@ +#include "../inc/data_type_def.h" +#include "../inc/clist.h" + +int32_t main(void) +{ + clist_node_t *head = NULL; // 创建头指针,初始化为NULL + clist_init(&head); // 初始化指针(可有可无) + + // 1:添加数据 + for (int32_t i = 0; i < 30; i++) + { + if (i > 10) + clist_push_front(&head, (cnode)i); // 头部插入 + else + clist_push_back(&head, (cnode)i); // 尾部插入 + } + + LOG_PRINT("\n 1: count:%d \n", clist_node_count(head)); // 获取链表节点数,打印 + clist_print(head); // 打印链表 + + // 2:删除数据 + for (int32_t i = 0; i < 10; i++) + { + if (i > 5) + clist_pop_back(&head); // 删除尾部 + else + clist_pop_front(&head); // 头部删除 + } + LOG_PRINT("\n 2: count:%d \n", clist_node_count(head)); + clist_print(head); + + // 3:插入数据 + clist_insert(&head, 5, (cnode)1111); + clist_insert_for_node(&head, head->Next->Next->Next->Next->Next, (cnode)10000); + clist_insert(&head, 1000, (cnode)2222); // 无效插入 + LOG_PRINT("\n 3: count:%d \n", clist_node_count(head)); + clist_print(head); + + // 4:删除指定节点 + clist_remove(&head, (cnode)5); + clist_erase_for_node(&head, head->Next->Next); + clist_remove(&head, (cnode)1000); // 无效删除 + clist_print(head); + LOG_PRINT("\n 4: count:%d \n", clist_node_count(head)); + clist_print(head); + + // 5:删除所有节点 + clist_destroy(&head); + LOG_PRINT("\n 5: count:%d ", clist_node_count(head)); + clist_print(head); + return 0; +} diff --git a/User/lib/examples/simple_cmac.c b/User/lib/examples/simple_cmac.c new file mode 100644 index 0000000..a96726f --- /dev/null +++ b/User/lib/examples/simple_cmac.c @@ -0,0 +1,33 @@ +#include "../inc/data_type_def.h" +#include "../inc/log.h" +#include "../inc/osel_arch.h" +#include "../inc/cmac.h" + +static uint8_t key[] = { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; // 密钥 +int32_t main(void) +{ + uint8_t *p; + uint8_t buffer[16] = {0x00}; + uint32_t size = ARRAY_LEN(buffer); + // 初始化需要校验的数据 + for (int i = 0; i < size; i++) + { + buffer[i] = i; + } + uint8_t mic[16]; // 存放生成校验数据的数组 + AES_CMAC_CTX AesCmacCtx[1]; // 密钥扩展表 + AES_CMAC_Init(AesCmacCtx); // 完成密钥扩展表的初始化 + + AES_CMAC_SetKey(AesCmacCtx, key); // 完成密钥扩展表数据 + + AES_CMAC_Update(AesCmacCtx, buffer, size & 0xFF); // 完成数据的奇偶校验 + + AES_CMAC_Final(mic, AesCmacCtx); // 生成16个字节的校验表 + + uint32_t xor_vol = (uint32_t)((uint32_t)mic[3] << 24 | (uint32_t)mic[2] << 16 | (uint32_t)mic[1] << 8 | (uint32_t)mic[0]); // 取表4个字节作为校验码 + + p = (uint8_t *)&xor_vol; + LOG_HEX(p, 4); // 打印结果:5c 7e fb 43 +} diff --git a/User/lib/examples/simple_cmd.c b/User/lib/examples/simple_cmd.c new file mode 100644 index 0000000..563e759 --- /dev/null +++ b/User/lib/examples/simple_cmd.c @@ -0,0 +1,26 @@ +#include "../inc/data_type_def.h" +#include "../inc/log.h" +#include "../inc/cmd.h" + +void at_name_req(void) +{ + LOG_PRINT("name:cmd\n"); +} + +void at_version_req(void) +{ + LOG_PRINT("version:1.0\n"); +} + +REGISTER_CMD(NAME, at_name_req, at name); +REGISTER_CMD(VERSION, at_version_req, at version); + +int32_t main(void) +{ + cmd_init(); + + cmd_parsing("TEST"); + cmd_parsing("NAME"); + cmd_parsing("VERSION"); + return 0; +} diff --git a/User/lib/examples/simple_data_analysis.c b/User/lib/examples/simple_data_analysis.c new file mode 100644 index 0000000..41d38ad --- /dev/null +++ b/User/lib/examples/simple_data_analysis.c @@ -0,0 +1,178 @@ +#include "../inc/data_type_def.h" +#include "../inc/log.h" +#include "../inc/osel_arch.h" +#include "../inc/data_analysis.h" +#define UART_RXSIZE (254U) +#define UART_DATA_ANALYSIS_PORT_1 DATA_1 +#define UART_DATA_ANALYSIS_PORT_2 DATA_2 + +static data_interupt_cb_t uart_data_analysis_cb = NULL; // 数据源中断回调函数 + +static void data_analysis_event1(void) +{ + uint8_t frame[UART_RXSIZE]; + uint8_t data_head[3]; + uint8_t crc[2]; + uint16_t frame_len, out_frame_len; + data_read(UART_DATA_ANALYSIS_PORT_1, &data_head[0], 3); + osel_memcpy((uint8_t *)&frame_len, &data_head[1], 2); + + frame_len = B2S_UINT16(frame_len) - 2; // 报文长度包含帧长,这里需要减2 + if (frame_len > UART_RXSIZE) + { + lock_data(UART_DATA_ANALYSIS_PORT_1); + unlock_data(UART_DATA_ANALYSIS_PORT_1); + return; + } + + out_frame_len = data_read(UART_DATA_ANALYSIS_PORT_1, frame, (uint16_t)frame_len); + if (out_frame_len != frame_len) + { + return; + } + out_frame_len = out_frame_len - 1; // 报文中包含帧尾,这里需要减1 + + // 校验CRC_16 + uint16_t crc_16 = 0; + uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2); + osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2); + crc_16 = BUILD_UINT16(crc[1], crc[0]); + if (crc16 != crc_16) + { + return; + } + // CRC校验通过后将数据长度-2 + out_frame_len -= 2; + + LOG_PRINT("data_analysis_event1 ok:"); + LOG_HEX(frame, out_frame_len); +} + +static void data_analysis_event2(void) +{ + uint8_t frame[UART_RXSIZE]; + uint8_t data_head[4]; + uint8_t crc[2]; + uint16_t frame_len, out_frame_len; + data_read(UART_DATA_ANALYSIS_PORT_2, &data_head[0], 4); + osel_memcpy((uint8_t *)&frame_len, &data_head[2], 2); + frame_len = B2S_UINT16(frame_len); + if (frame_len > UART_RXSIZE) + { + lock_data(UART_DATA_ANALYSIS_PORT_2); + unlock_data(UART_DATA_ANALYSIS_PORT_2); + return; + } + + out_frame_len = data_read(UART_DATA_ANALYSIS_PORT_2, frame, (uint16_t)frame_len); + if (out_frame_len != frame_len) + { + return; + } + + // 校验CRC_16 + uint16_t crc_16 = 0; + uint16_t crc16 = crc16_compute(&frame[0], out_frame_len - 2); + osel_memcpy(&crc[0], &frame[out_frame_len - 2], 2); + crc_16 = BUILD_UINT16(crc[1], crc[0]); + if (crc16 != crc_16) + { + LOG_PRINT("crc error crc16:%x, crc_16:%x\n"); + return; + } + + out_frame_len -= 2; // 去掉CRC_16 + + LOG_PRINT("data_analysis_event2 ok:"); + LOG_HEX(frame, out_frame_len); +} +/** + * @brief 需要识别帧头和帧尾的数据协议 + * @return {*} + * @note + */ +static void data_register1(void) +{ +/** + * 帧头 帧长度 源地址 目标地址 报文类型 报文体 校验 帧尾 + 1 2 2 2 1 n 2 1 +*/ +#define FRAME_HEAD 0x05 // 帧头 +#define FRAME_TAIL 0x1b // 帧尾 + + // 注册数据解析 + data_reg_t reg; + reg.sd.valid = true; // 数据头部验证有效标志位 + reg.sd.len = 1; // 数据头部长度 + reg.sd.pos = 0; // 数据头部偏移量 + reg.sd.data[0] = FRAME_HEAD; // 数据头部数据 + reg.ld.len = 2; // 数据长度 + reg.ld.pos = 2; // 报文长度包含帧长,这里需要设置偏移2 + reg.ld.valid = true; // 数据长度有效标志位 + reg.ld.little_endian = false; // 数据长度是否小端模式 + reg.argu.len_max = UART_RXSIZE; // 数据最大长度 + reg.argu.len_min = 2; // 数据最小长度 + reg.ed.valid = true; // 数据尾部有效标志位 + reg.ed.len = 1; // 数据尾部长度 + reg.ed.data[0] = FRAME_TAIL; // 数据尾部数据 + reg.echo_en = false; // 是否回显 + reg.func_ptr = data_analysis_event1; // 数据解析回调函数 data_analysis模块处理完数据后,会调用这个函数继续数据协议的处理 + uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT_1); // 注册数据处理函数 data_analysis模块会调用这个函数,将数据写入到data_analysis模块 + data_reg(UART_DATA_ANALYSIS_PORT_1, reg); // 注册数据解析 +} + +/** + * @brief 需要识别帧头和没有帧尾的数据协议 + * @return {*} + * @note + */ +static void data_register2(void) +{ +/** + * 帧头 帧长度 源地址 目标地址 报文类型 报文体 校验 + 2 2 2 2 1 n 2 +*/ +#define FRAME_HEAD1 0xD5 // 帧头 +#define FRAME_HEAD2 0xC8 // 帧尾 + + // 注册数据解析 + data_reg_t reg; + reg.sd.valid = true; // 数据头部验证有效标志位 + reg.sd.len = 2; // 数据头部长度 + reg.sd.pos = 0; // 数据头部偏移量 + reg.sd.data[0] = FRAME_HEAD1; // 数据头部数据 + reg.sd.data[1] = FRAME_HEAD2; // 数据头部数据 + reg.ld.len = 2; // 数据长度 + reg.ld.pos = 2; // 报文长度包含帧长,这里需要设置偏移2 + reg.ld.valid = true; // 数据长度有效标志位 + reg.ld.little_endian = false; // 数据长度是否小端模式 + reg.argu.len_max = UART_RXSIZE; // 数据最大长度 + reg.argu.len_min = 2; // 数据最小长度 + reg.ed.valid = false; // 数据尾部有效标志位 + reg.echo_en = false; // 是否回显 + reg.func_ptr = data_analysis_event2; // 数据解析回调函数 data_analysis模块处理完数据后,会调用这个函数继续数据协议的处理 + uart_data_analysis_cb = data_fsm_init(UART_DATA_ANALYSIS_PORT_2); // 注册数据处理函数 data_analysis模块会调用这个函数,将数据写入到data_analysis模块 + data_reg(UART_DATA_ANALYSIS_PORT_2, reg); // 注册数据解析 +} + +int32_t main(void) +{ + data_register1(); + data_register2(); + + // 模拟串口数据 + uint8_t data1[] = {0x05, 0x00, 0x0a, 0xff, 0xff, 0x00, 0x01, 0x00, 0x55, 0x40, 0x1b}; + for (uint16_t i = 0; i < ARRAY_LEN(data1); i++) + { + uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT_1, *(data1 + i)); + } + + // 模拟串口数据 + uint8_t data2[] = {0xD5, 0xC8, 0x00, 0x07, 0xff, 0xff, 0x00, 0x01, 0x00, 0x55, 0x40}; + for (uint16_t i = 0; i < ARRAY_LEN(data2); i++) + { + uart_data_analysis_cb(UART_DATA_ANALYSIS_PORT_2, *(data2 + i)); + } + + return 0; +} diff --git a/User/lib/examples/simple_sqqueue.c b/User/lib/examples/simple_sqqueue.c new file mode 100644 index 0000000..3ed8c91 --- /dev/null +++ b/User/lib/examples/simple_sqqueue.c @@ -0,0 +1,53 @@ +#include "../inc/data_type_def.h" +#include "../inc/log.h" +#include "../inc/osel_arch.h" +#include "../inc/sqqueue.h" + +typedef struct +{ + uint8_t x; + uint8_t y; +} element_t; + +sqqueue_ctrl_t queue; // 创建队列对象 + +void traverse_cb(const void *e) +{ + element_t *p = (element_t *)e; + LOG_PRINT("x = %d, y = %d", p->x, p->y); +} + +int32_t main(void) +{ + int size = 10; + // 初始化队列 + if (FALSE == sqqueue_ctrl_init(&queue, sizeof(element_t), size)) + { + LOG_ERR("queue init failed!"); + return -1; // 创建失败 + } + + // 添加测试元素 + for (int i = 1; i <= 10; i++) + { + element_t element; + element.x = i * 10; + element.y = i * 10; + queue.enter(&queue, &element); // 将成员插入到队列中 + } + LOG_PRINT("add queue len = %d", queue.get_len(&queue)); // 获取队列长度 + + queue.del(&queue); // 移除首元素 + LOG_PRINT("del queue len = %d", queue.get_len(&queue)); // 获取队列长度 + queue.revoke(&queue); // 移除尾元素 + LOG_PRINT("revoke queue len = %d", queue.get_len(&queue)); // 获取队列长度 + queue.remove(&queue, 3); // 删除相对队头指定偏移位置的元素 + LOG_PRINT("remove queue len = %d", queue.get_len(&queue)); // 获取队列长度 + + LOG_PRINT("queue traverse:"); + queue.traverse(&queue, traverse_cb); // 遍历队列 + + queue.clear_sqq(&queue); // 清空队列 + LOG_PRINT("clear queue len = %d", queue.get_len(&queue)); // 获取队列长度 + return 0; +} diff --git a/User/lib/flashdb/examples/kvdb_basic_sample.c b/User/lib/flashdb/examples/kvdb_basic_sample.c new file mode 100644 index 0000000..01e1c0f --- /dev/null +++ b/User/lib/flashdb/examples/kvdb_basic_sample.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief basic KV samples. + * + * basic Key-Value Database KV feature samples + * get and show currnet boot counts + */ + +#include + +#ifdef FDB_USING_KVDB + +#define FDB_LOG_TAG "[sample][kvdb][basic]" + +void kvdb_basic_sample(fdb_kvdb_t kvdb) +{ + struct fdb_blob blob; + int boot_count = 0; + + FDB_INFO("==================== kvdb_basic_sample ====================\n"); + + { /* GET the KV value */ + /* get the "boot_count" KV value */ + fdb_kv_get_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); + /* the blob.saved.len is more than 0 when get the value successful */ + if (blob.saved.len > 0) { + FDB_INFO("get the 'boot_count' value is %d\n", boot_count); + } else { + FDB_INFO("get the 'boot_count' failed\n"); + } + } + + { /* CHANGE the KV value */ + /* increase the boot count */ + boot_count ++; + /* change the "boot_count" KV's value */ + fdb_kv_set_blob(kvdb, "boot_count", fdb_blob_make(&blob, &boot_count, sizeof(boot_count))); + FDB_INFO("set the 'boot_count' value to %d\n", boot_count); + } + + FDB_INFO("===========================================================\n"); +} + +#endif /* FDB_USING_KVDB */ diff --git a/User/lib/flashdb/examples/kvdb_type_blob_sample.c b/User/lib/flashdb/examples/kvdb_type_blob_sample.c new file mode 100644 index 0000000..f37983c --- /dev/null +++ b/User/lib/flashdb/examples/kvdb_type_blob_sample.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief blob KV samples. + * + * Key-Value Database blob type KV feature samples + */ + +#include + +#ifdef FDB_USING_KVDB + +#define FDB_LOG_TAG "[sample][kvdb][blob]" + +void kvdb_type_blob_sample(fdb_kvdb_t kvdb) +{ + struct fdb_blob blob; + + FDB_INFO("==================== kvdb_type_blob_sample ====================\n"); + + { /* CREATE new Key-Value */ + int temp_data = 36; + + /* It will create new KV node when "temp" KV not in database. + * fdb_blob_make: It's a blob make function, and it will return the blob when make finish. + */ + fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data))); + FDB_INFO("create the 'temp' blob KV, value is: %d\n", temp_data); + } + + { /* GET the KV value */ + int temp_data = 0; + + /* get the "temp" KV value */ + fdb_kv_get_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data))); + /* the blob.saved.len is more than 0 when get the value successful */ + if (blob.saved.len > 0) { + FDB_INFO("get the 'temp' value is: %d\n", temp_data); + } + } + + { /* CHANGE the KV value */ + int temp_data = 38; + + /* change the "temp" KV's value to 38 */ + fdb_kv_set_blob(kvdb, "temp", fdb_blob_make(&blob, &temp_data, sizeof(temp_data))); + FDB_INFO("set 'temp' value to %d\n", temp_data); + } + + { /* DELETE the KV by name */ + fdb_kv_del(kvdb, "temp"); + FDB_INFO("delete the 'temp' finish\n"); + } + + FDB_INFO("===========================================================\n"); +} + +#endif /* FDB_USING_KVDB */ diff --git a/User/lib/flashdb/examples/kvdb_type_string_sample.c b/User/lib/flashdb/examples/kvdb_type_string_sample.c new file mode 100644 index 0000000..90e6598 --- /dev/null +++ b/User/lib/flashdb/examples/kvdb_type_string_sample.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief string KV samples. + * + * Key-Value Database string type KV feature samples source file. + */ + +#include +#include + +#ifdef FDB_USING_KVDB + +#define FDB_LOG_TAG "[sample][kvdb][string]" + +void kvdb_type_string_sample(fdb_kvdb_t kvdb) +{ + FDB_INFO("==================== kvdb_type_string_sample ====================\n"); + + { /* CREATE new Key-Value */ + char temp_data[10] = "36C"; + + /* It will create new KV node when "temp" KV not in database. */ + fdb_kv_set(kvdb, "temp", temp_data); + FDB_INFO("create the 'temp' string KV, value is: %s\n", temp_data); + } + + { /* GET the KV value */ + char *return_value, temp_data[10] = { 0 }; + + /* Get the "temp" KV value. + * NOTE: The return value saved in fdb_kv_get's buffer. Please copy away as soon as possible. + */ + return_value = fdb_kv_get(kvdb, "temp"); + /* the return value is NULL when get the value failed */ + if (return_value != NULL) { + strncpy(temp_data, return_value, sizeof(temp_data)); + FDB_INFO("get the 'temp' value is: %s\n", temp_data); + } + } + + { /* CHANGE the KV value */ + char temp_data[10] = "38C"; + + /* change the "temp" KV's value to "38.1" */ + fdb_kv_set(kvdb, "temp", temp_data); + FDB_INFO("set 'temp' value to %s\n", temp_data); + } + + { /* DELETE the KV by name */ + fdb_kv_del(kvdb, "temp"); + FDB_INFO("delete the 'temp' finish\n"); + } + + FDB_INFO("===========================================================\n"); +} + +#endif /* FDB_USING_KVDB */ diff --git a/User/lib/flashdb/examples/tsdb_sample.c b/User/lib/flashdb/examples/tsdb_sample.c new file mode 100644 index 0000000..173ceb1 --- /dev/null +++ b/User/lib/flashdb/examples/tsdb_sample.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief TSDB samples. + * + * Time series log (like TSDB) feature samples source file. + * + * TSL is time series log, the TSDB saved many TSLs. + */ + +#include +#include + +#ifdef FDB_USING_TSDB + +#define FDB_LOG_TAG "[sample][tsdb]" + +#ifdef FDB_USING_TIMESTAMP_64BIT +#define __PRITS "ld" +#else +#define __PRITS "d" +#endif + +struct env_status { + int temp; + int humi; +}; + +static bool query_cb(fdb_tsl_t tsl, void *arg); +static bool query_by_time_cb(fdb_tsl_t tsl, void *arg); +static bool set_status_cb(fdb_tsl_t tsl, void *arg); + +void tsdb_sample(fdb_tsdb_t tsdb) +{ + struct fdb_blob blob; + + FDB_INFO("==================== tsdb_sample ====================\n"); + + { /* APPEND new TSL (time series log) */ + struct env_status status; + + /* append new log to TSDB */ + status.temp = 36; + status.humi = 85; + fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status))); + FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi); + + status.temp = 38; + status.humi = 90; + fdb_tsl_append(tsdb, fdb_blob_make(&blob, &status, sizeof(status))); + FDB_INFO("append the new status.temp (%d) and status.humi (%d)\n", status.temp, status.humi); + } + + { /* QUERY the TSDB */ + /* query all TSL in TSDB by iterator */ + fdb_tsl_iter(tsdb, query_cb, tsdb); + } + + { /* QUERY the TSDB by time */ + /* prepare query time (from 1970-01-01 00:00:00 to 2020-05-05 00:00:00) */ + struct tm tm_from = { .tm_year = 1970 - 1900, .tm_mon = 0, .tm_mday = 1, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 }; + struct tm tm_to = { .tm_year = 2020 - 1900, .tm_mon = 4, .tm_mday = 5, .tm_hour = 0, .tm_min = 0, .tm_sec = 0 }; + time_t from_time = mktime(&tm_from), to_time = mktime(&tm_to); + size_t count; + /* query all TSL in TSDB by time */ + fdb_tsl_iter_by_time(tsdb, from_time, to_time, query_by_time_cb, tsdb); + /* query all FDB_TSL_WRITE status TSL's count in TSDB by time */ + count = fdb_tsl_query_count(tsdb, from_time, to_time, FDB_TSL_WRITE); + FDB_INFO("query count is: %zu\n", count); + } + + { /* SET the TSL status */ + /* Change the TSL status by iterator or time iterator + * set_status_cb: the change operation will in this callback + * + * NOTE: The actions to modify the state must be in order. + * like: FDB_TSL_WRITE -> FDB_TSL_USER_STATUS1 -> FDB_TSL_DELETED -> FDB_TSL_USER_STATUS2 + * The intermediate states can also be ignored. + * such as: FDB_TSL_WRITE -> FDB_TSL_DELETED + */ + fdb_tsl_iter(tsdb, set_status_cb, tsdb); + } + + FDB_INFO("===========================================================\n"); +} + +static bool query_cb(fdb_tsl_t tsl, void *arg) +{ + struct fdb_blob blob; + struct env_status status; + fdb_tsdb_t db = arg; + + fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status)))); + FDB_INFO("[query_cb] queried a TSL: time: %" __PRITS ", temp: %d, humi: %d\n", tsl->time, status.temp, status.humi); + + return false; +} + +static bool query_by_time_cb(fdb_tsl_t tsl, void *arg) +{ + struct fdb_blob blob; + struct env_status status; + fdb_tsdb_t db = arg; + + fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status)))); + FDB_INFO("[query_by_time_cb] queried a TSL: time: %" __PRITS ", temp: %d, humi: %d\n", tsl->time, status.temp, status.humi); + + return false; +} + +static bool set_status_cb(fdb_tsl_t tsl, void *arg) +{ + fdb_tsdb_t db = arg; + + FDB_INFO("set the TSL (time %" __PRITS ") status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1); + fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1); + + return false; +} + +#endif /* FDB_USING_TSDB */ diff --git a/User/lib/flashdb/fal/fal.c b/User/lib/flashdb/fal/fal.c new file mode 100644 index 0000000..85d4660 --- /dev/null +++ b/User/lib/flashdb/fal/fal.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-17 armink the first version + */ + +#include + +static uint8_t init_ok = 0; + +/** + * FAL (Flash Abstraction Layer) initialization. + * It will initialize all flash device and all flash partition. + * + * @return >= 0: partitions total number + */ +int fal_init(void) +{ + extern int fal_flash_init(void); + extern int fal_partition_init(void); + + int result; + + /* initialize all flash device on FAL flash table */ + result = fal_flash_init(); + + if (result < 0) { + goto __exit; + } + + /* initialize all flash partition on FAL partition table */ + result = fal_partition_init(); + +__exit: + + if ((result > 0) && (!init_ok)) + { + init_ok = 1; + log_i("Flash Abstraction Layer (V%s) initialize success.", FAL_SW_VERSION); + } + else if(result <= 0) + { + init_ok = 0; + log_e("Flash Abstraction Layer (V%s) initialize failed.", FAL_SW_VERSION); + } + + return result; +} + +/** + * Check if the FAL is initialized successfully + * + * @return 0: not init or init failed; 1: init success + */ +int fal_init_check(void) +{ + return init_ok; +} diff --git a/User/lib/flashdb/fal/fal.h b/User/lib/flashdb/fal/fal.h new file mode 100644 index 0000000..19a996f --- /dev/null +++ b/User/lib/flashdb/fal/fal.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-17 armink the first version + */ + +#ifndef _FAL_H_ +#define _FAL_H_ + +#include +#include "fal_def.h" + +/** + * FAL (Flash Abstraction Layer) initialization. + * It will initialize all flash device and all flash partition. + * + * @return >= 0: partitions total number + */ +int fal_init(void); + +/* =============== flash device operator API =============== */ +/** + * find flash device by name + * + * @param name flash device name + * + * @return != NULL: flash device + * NULL: not found + */ +const struct fal_flash_dev *fal_flash_device_find(const char *name); + +/* =============== partition operator API =============== */ +/** + * find the partition by name + * + * @param name partition name + * + * @return != NULL: partition + * NULL: not found + */ +const struct fal_partition *fal_partition_find(const char *name); + +/** + * get the partition table + * + * @param len return the partition table length + * + * @return partition table + */ +const struct fal_partition *fal_get_partition_table(size_t *len); + +/** + * set partition table temporarily + * This setting will modify the partition table temporarily, the setting will be lost after restart. + * + * @param table partition table + * @param len partition table length + */ +void fal_set_partition_table_temp(struct fal_partition *table, size_t len); + +/** + * read data from partition + * + * @param part partition + * @param addr relative address for partition + * @param buf read buffer + * @param size read size + * + * @return >= 0: successful read data size + * -1: error + */ +int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size); + +/** + * write data to partition + * + * @param part partition + * @param addr relative address for partition + * @param buf write buffer + * @param size write size + * + * @return >= 0: successful write data size + * -1: error + */ +int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size); + +/** + * erase partition data + * + * @param part partition + * @param addr relative address for partition + * @param size erase size + * + * @return >= 0: successful erased data size + * -1: error + */ +int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size); + +/** + * erase partition all data + * + * @param part partition + * + * @return >= 0: successful erased data size + * -1: error + */ +int fal_partition_erase_all(const struct fal_partition *part); + +/** + * print the partition table + */ +void fal_show_part_table(void); + +/* =============== API provided to RT-Thread =============== */ +/** + * create RT-Thread block device by specified partition + * + * @param parition_name partition name + * + * @return != NULL: created block device + * NULL: created failed + */ +struct rt_device *fal_blk_device_create(const char *parition_name); + +#if defined(RT_USING_MTD_NOR) +/** + * create RT-Thread MTD NOR device by specified partition + * + * @param parition_name partition name + * + * @return != NULL: created MTD NOR device + * NULL: created failed + */ +struct rt_device *fal_mtd_nor_device_create(const char *parition_name); +#endif /* defined(RT_USING_MTD_NOR) */ + +/** + * create RT-Thread char device by specified partition + * + * @param parition_name partition name + * + * @return != NULL: created char device + * NULL: created failed + */ +struct rt_device *fal_char_device_create(const char *parition_name); + +#endif /* _FAL_H_ */ diff --git a/User/lib/flashdb/fal/fal_cfg.h b/User/lib/flashdb/fal/fal_cfg.h new file mode 100644 index 0000000..722194c --- /dev/null +++ b/User/lib/flashdb/fal/fal_cfg.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-17 armink the first version + */ + +#ifndef _FAL_CFG_H_ +#define _FAL_CFG_H_ +#include "eeprom_m95.h" +#include "eeprom_fm24.h" + +#define FAL_PART_HAS_TABLE_CFG + +#define EEPROM_M95_1_BLOCK_SIZE M95_PAGE_SIZE_128 * 64 +#define EEPROM_M95_2_BLOCK_SIZE M95_PAGE_SIZE_256 * 32 +#define EEPROM_FM24_BLOCK_SIZE FM24_PAGE_SIZE * 8 + +#define EEPROM_M95_1_SIZE _M95512_ +#define EEPROM_M95_2_SIZE _M95M02_ +#define EEPROM_FM24_SIZE FM24_SIZE + +#define EEPROM_M95_1_DEV_NAME "eeprom_m95_1" +#define EEPROM_M95_2_DEV_NAME "eeprom_m95_2" +#define EEPROM_FM24_DEV_NAME "eeprom_fm24" + +/* ===================== Flash device Configuration ========================= */ +extern struct fal_flash_dev eeprom_m95_1; +extern struct fal_flash_dev eeprom_m95_2; +extern struct fal_flash_dev eeprom_fm24; + +/* flash device table */ +#define FAL_FLASH_DEV_TABLE \ + { \ + &eeprom_m95_1, \ + &eeprom_m95_2, \ + &eeprom_fm24, \ + } + +/* ====================== Partition Configuration ========================== */ +#ifdef FAL_PART_HAS_TABLE_CFG +/* partition table */ +// issues :https://github.com/armink/FlashDB/issues/40 ;epprom的扇区太小 +#define FAL_PART_TABLE \ + { \ + {FAL_PART_MAGIC_WORD, "KVDB", EEPROM_M95_1_DEV_NAME, 0, EEPROM_M95_1_SIZE, 0}, \ + {FAL_PART_MAGIC_WORD, "TSDB", EEPROM_M95_2_DEV_NAME, 0, EEPROM_M95_2_SIZE, 0}, \ + {FAL_PART_MAGIC_WORD, "RTDB", EEPROM_FM24_DEV_NAME, 0, EEPROM_FM24_SIZE, 0}, \ + } + +#endif /* FAL_PART_HAS_TABLE_CFG */ + +#endif /* _FAL_CFG_H_ */ diff --git a/User/lib/flashdb/fal/fal_def.h b/User/lib/flashdb/fal/fal_def.h new file mode 100644 index 0000000..afdbc0b --- /dev/null +++ b/User/lib/flashdb/fal/fal_def.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-17 armink the first version + */ + +#ifndef _FAL_DEF_H_ +#define _FAL_DEF_H_ + +#include +#include +#ifdef FDB_USING_NATIVE_ASSERT +#include +#endif + +#define FAL_SW_VERSION "0.5.99" + +#ifdef __RTTHREAD__ /* for RT-Thread platform */ +#include +#define FAL_PRINTF rt_kprintf +#define FAL_MALLOC rt_malloc +#define FAL_CALLOC rt_calloc +#define FAL_REALLOC rt_realloc +#define FAL_FREE rt_free +#endif + +#ifndef FAL_MALLOC +#define FAL_MALLOC malloc +#endif + +#ifndef FAL_CALLOC +#define FAL_CALLOC calloc +#endif + +#ifndef FAL_REALLOC +#define FAL_REALLOC realloc +#endif + +#ifndef FAL_FREE +#define FAL_FREE free +#endif + +// #ifndef FAL_PRINTF +// #define FAL_PRINTF printf +// #endif + +#ifndef FAL_PRINTF +#define FAL_PRINTF(...) \ + do \ + { \ + } while (0); +#endif + +#ifndef FAL_DEBUG +#define FAL_DEBUG 0 +#endif + +#if FAL_DEBUG +#ifndef FDB_USING_NATIVE_ASSERT +#ifdef assert +#undef assert +#endif +#define assert(EXPR) \ + if (!(EXPR)) \ + { \ + FAL_PRINTF("(%s) has assert failed at %s.\n", #EXPR, __func__); \ + while (1) \ + ; \ + } +#endif + +/* debug level log */ +#ifdef log_d +#undef log_d +#endif +#include +#define log_d(...) \ + FAL_PRINTF("[D/FAL] (%s:%" PRIdLEAST16 ") ", __func__, __LINE__); \ + FAL_PRINTF(__VA_ARGS__); \ + FAL_PRINTF("\n") + +#else + +#ifndef FDB_USING_NATIVE_ASSERT +#ifdef assert +#undef assert +#endif +#define assert(EXPR) ((void)0); +#endif + +/* debug level log */ +#ifdef log_d +#undef log_d +#endif +#define log_d(...) +#endif /* FAL_DEBUG */ + +/* error level log */ +#ifdef log_e +#undef log_e +#endif +#define log_e(...) \ + FAL_PRINTF("\033[31;22m[E/FAL] (%s:%d) ", __func__, __LINE__); \ + FAL_PRINTF(__VA_ARGS__); \ + FAL_PRINTF("\033[0m\n") + +/* info level log */ +#ifdef log_i +#undef log_i +#endif +#define log_i(...) \ + FAL_PRINTF("\033[32;22m[I/FAL] "); \ + FAL_PRINTF(__VA_ARGS__); \ + FAL_PRINTF("\033[0m\n") + +/* FAL flash and partition device name max length */ +#ifndef FAL_DEV_NAME_MAX +#define FAL_DEV_NAME_MAX 24 +#endif + +struct fal_flash_dev +{ + char name[FAL_DEV_NAME_MAX]; + + /* flash device start address and len */ + uint32_t addr; + size_t len; + /* the block size in the flash for erase minimum granularity */ + size_t blk_size; + + struct + { + int (*init)(void); + int (*read)(long offset, uint8_t *buf, size_t size); + int (*write)(long offset, const uint8_t *buf, size_t size); + int (*erase)(long offset, size_t size); + } ops; + + /* write minimum granularity, unit: bit. + 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32l4) + 0 will not take effect. */ + size_t write_gran; +}; +typedef struct fal_flash_dev *fal_flash_dev_t; + +/** + * FAL partition + */ +struct fal_partition +{ + uint32_t magic_word; + + /* partition name */ + char name[FAL_DEV_NAME_MAX]; + /* flash device name for partition */ + char flash_name[FAL_DEV_NAME_MAX]; + + /* partition offset address on flash device */ + long offset; + size_t len; + + uint32_t reserved; +}; +typedef struct fal_partition *fal_partition_t; + +#endif /* _FAL_DEF_H_ */ diff --git a/User/lib/flashdb/fal/fal_flash.c b/User/lib/flashdb/fal/fal_flash.c new file mode 100644 index 0000000..8cef82c --- /dev/null +++ b/User/lib/flashdb/fal/fal_flash.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-17 armink the first version + */ + +#include +#include + +/* flash device table, must defined by user */ +#if !defined(FAL_FLASH_DEV_TABLE) +#error "You must defined flash device table (FAL_FLASH_DEV_TABLE) on 'fal_cfg.h'" +#endif + +static const struct fal_flash_dev * const device_table[] = FAL_FLASH_DEV_TABLE; +static const size_t device_table_len = sizeof(device_table) / sizeof(device_table[0]); +static uint8_t init_ok = 0; + +/** + * Initialize all flash device on FAL flash table + * + * @return result + */ +int fal_flash_init(void) +{ + size_t i; + + if (init_ok) + { + return 0; + } + + for (i = 0; i < device_table_len; i++) + { + assert(device_table[i]->ops.read); + assert(device_table[i]->ops.write); + assert(device_table[i]->ops.erase); + /* init flash device on flash table */ + if (device_table[i]->ops.init) + { + device_table[i]->ops.init(); + } + log_d("Flash device | %*.*s | addr: 0x%08lx | len: 0x%08x | blk_size: 0x%08x |initialized finish.", + FAL_DEV_NAME_MAX, FAL_DEV_NAME_MAX, device_table[i]->name, device_table[i]->addr, device_table[i]->len, + device_table[i]->blk_size); + } + + init_ok = 1; + return 0; +} + +/** + * find flash device by name + * + * @param name flash device name + * + * @return != NULL: flash device + * NULL: not found + */ +const struct fal_flash_dev *fal_flash_device_find(const char *name) +{ + assert(init_ok); + assert(name); + + size_t i; + + for (i = 0; i < device_table_len; i++) + { + if (!strncmp(name, device_table[i]->name, FAL_DEV_NAME_MAX)) { + return device_table[i]; + } + } + + return NULL; +} diff --git a/User/lib/flashdb/fal/fal_partition.c b/User/lib/flashdb/fal/fal_partition.c new file mode 100644 index 0000000..a24e631 --- /dev/null +++ b/User/lib/flashdb/fal/fal_partition.c @@ -0,0 +1,525 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-17 armink the first version + */ + +#include +#include +#include + +/* partition magic word */ +#define FAL_PART_MAGIC_WORD 0x45503130 +#define FAL_PART_MAGIC_WORD_H 0x4550L +#define FAL_PART_MAGIC_WORD_L 0x3130L + +struct part_flash_info +{ + const struct fal_flash_dev *flash_dev; +}; + +/** + * FAL partition table config has defined on 'fal_cfg.h'. + * When this option is disable, it will auto find the partition table on a specified location in flash partition. + */ +#ifdef FAL_PART_HAS_TABLE_CFG + +/* check partition table definition */ +#if !defined(FAL_PART_TABLE) +#error "You must defined FAL_PART_TABLE on 'fal_cfg.h'" +#endif + +#ifdef __CC_ARM /* ARM Compiler */ + #define SECTION(x) __attribute__((section(x))) + #define USED __attribute__((used)) +#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */ + #define SECTION(x) @ x + #define USED __root +#elif defined (__GNUC__) /* GNU GCC Compiler */ + #define SECTION(x) __attribute__((section(x))) + #define USED __attribute__((used)) +#else + #error not supported tool chain +#endif /* __CC_ARM */ +//USED static const struct fal_partition partition_table_def[] SECTION("FalPartTable") = FAL_PART_TABLE; +static const struct fal_partition partition_table_def[] = FAL_PART_TABLE; +static const struct fal_partition *partition_table = NULL; +/* partition and flash object information cache table */ +static struct part_flash_info part_flash_cache[sizeof(partition_table_def) / sizeof(partition_table_def[0])] = { 0 }; + +#else /* FAL_PART_HAS_TABLE_CFG */ + +#if !defined(FAL_PART_TABLE_FLASH_DEV_NAME) +#error "You must defined FAL_PART_TABLE_FLASH_DEV_NAME on 'fal_cfg.h'" +#endif + +/* check partition table end offset address definition */ +#if !defined(FAL_PART_TABLE_END_OFFSET) +#error "You must defined FAL_PART_TABLE_END_OFFSET on 'fal_cfg.h'" +#endif + +static struct fal_partition *partition_table = NULL; +static struct part_flash_info *part_flash_cache = NULL; +#endif /* FAL_PART_HAS_TABLE_CFG */ + +static uint8_t init_ok = 0; +static size_t partition_table_len = 0; + +/** + * print the partition table + */ +void fal_show_part_table(void) +{ + char *item1 = "name", *item2 = "flash_dev"; + size_t i, part_name_max = strlen(item1), flash_dev_name_max = strlen(item2); + const struct fal_partition *part; + + if (partition_table_len) + { + for (i = 0; i < partition_table_len; i++) + { + part = &partition_table[i]; + if (strlen(part->name) > part_name_max) + { + part_name_max = strlen(part->name); + } + if (strlen(part->flash_name) > flash_dev_name_max) + { + flash_dev_name_max = strlen(part->flash_name); + } + } + } + log_i("==================== FAL partition table ===================="); + log_i("| %-*.*s | %-*.*s | offset | length |", part_name_max, FAL_DEV_NAME_MAX, item1, flash_dev_name_max, + FAL_DEV_NAME_MAX, item2); + log_i("-------------------------------------------------------------"); + for (i = 0; i < partition_table_len; i++) + { + +#ifdef FAL_PART_HAS_TABLE_CFG + part = &partition_table[i]; +#else + part = &partition_table[partition_table_len - i - 1]; +#endif + + log_i("| %-*.*s | %-*.*s | 0x%08lx | 0x%08x |", part_name_max, FAL_DEV_NAME_MAX, part->name, flash_dev_name_max, + FAL_DEV_NAME_MAX, part->flash_name, part->offset, part->len); + } + log_i("============================================================="); +} + +static int check_and_update_part_cache(const struct fal_partition *table, size_t len) +{ + const struct fal_flash_dev *flash_dev = NULL; + size_t i; + +#ifndef FAL_PART_HAS_TABLE_CFG + if (part_flash_cache) + { + FAL_FREE(part_flash_cache); + } + part_flash_cache = FAL_MALLOC(len * sizeof(struct part_flash_info)); + if (part_flash_cache == NULL) + { + log_e("Initialize failed! No memory for partition table cache"); + return -2; + } +#endif + + for (i = 0; i < len; i++) + { + flash_dev = fal_flash_device_find(table[i].flash_name); + if (flash_dev == NULL) + { + log_d("Warning: Do NOT found the flash device(%s).", table[i].flash_name); + continue; + } + + if (table[i].offset >= (long)flash_dev->len) + { + log_e("Initialize failed! Partition(%s) offset address(%ld) out of flash bound(<%d).", + table[i].name, table[i].offset, flash_dev->len); + partition_table_len = 0; + + return -1; + } + + part_flash_cache[i].flash_dev = flash_dev; + } + + return 0; +} + +/** + * Initialize all flash partition on FAL partition table + * + * @return partitions total number + */ +int fal_partition_init(void) +{ + + if (init_ok) + { + return partition_table_len; + } + +#ifdef FAL_PART_HAS_TABLE_CFG + partition_table = &partition_table_def[0]; + partition_table_len = sizeof(partition_table_def) / sizeof(partition_table_def[0]); +#else + /* load partition table from the end address FAL_PART_TABLE_END_OFFSET, error return 0 */ + long part_table_offset = FAL_PART_TABLE_END_OFFSET; + size_t table_num = 0, table_item_size = 0; + uint8_t part_table_find_ok = 0; + uint32_t read_magic_word; + fal_partition_t new_part = NULL; + size_t i; + const struct fal_flash_dev *flash_dev = NULL; + + flash_dev = fal_flash_device_find(FAL_PART_TABLE_FLASH_DEV_NAME); + if (flash_dev == NULL) + { + log_e("Initialize failed! Flash device (%s) NOT found.", FAL_PART_TABLE_FLASH_DEV_NAME); + goto _exit; + } + + /* check partition table offset address */ + if (part_table_offset < 0 || part_table_offset >= (long) flash_dev->len) + { + log_e("Setting partition table end offset address(%ld) out of flash bound(<%d).", part_table_offset, flash_dev->len); + goto _exit; + } + + table_item_size = sizeof(struct fal_partition); + new_part = (fal_partition_t)FAL_MALLOC(table_item_size); + if (new_part == NULL) + { + log_e("Initialize failed! No memory for table buffer."); + goto _exit; + } + + /* find partition table location */ + { + uint8_t read_buf[64]; + + part_table_offset -= sizeof(read_buf); + while (part_table_offset >= 0) + { + if (flash_dev->ops.read(part_table_offset, read_buf, sizeof(read_buf)) > 0) + { + /* find magic word in read buf */ + for (i = 0; i < sizeof(read_buf) - sizeof(read_magic_word) + 1; i++) + { + read_magic_word = read_buf[0 + i] + (read_buf[1 + i] << 8) + (read_buf[2 + i] << 16) + (read_buf[3 + i] << 24); + if (read_magic_word == ((FAL_PART_MAGIC_WORD_H << 16) + FAL_PART_MAGIC_WORD_L)) + { + part_table_find_ok = 1; + part_table_offset += i; + log_d("Find the partition table on '%s' offset @0x%08lx.", FAL_PART_TABLE_FLASH_DEV_NAME, + part_table_offset); + break; + } + } + } + else + { + /* read failed */ + break; + } + + if (part_table_find_ok) + { + break; + } + else + { + /* calculate next read buf position */ + if (part_table_offset >= (long)sizeof(read_buf)) + { + part_table_offset -= sizeof(read_buf); + part_table_offset += (sizeof(read_magic_word) - 1); + } + else if (part_table_offset != 0) + { + part_table_offset = 0; + } + else + { + /* find failed */ + break; + } + } + } + } + + /* load partition table */ + while (part_table_find_ok) + { + memset(new_part, 0x00, table_num); + if (flash_dev->ops.read(part_table_offset - table_item_size * (table_num), (uint8_t *) new_part, + table_item_size) < 0) + { + log_e("Initialize failed! Flash device (%s) read error!", flash_dev->name); + table_num = 0; + break; + } + + if (new_part->magic_word != ((FAL_PART_MAGIC_WORD_H << 16) + FAL_PART_MAGIC_WORD_L)) + { + break; + } + + partition_table = (fal_partition_t) FAL_REALLOC(partition_table, table_item_size * (table_num + 1)); + if (partition_table == NULL) + { + log_e("Initialize failed! No memory for partition table"); + table_num = 0; + break; + } + + memcpy(partition_table + table_num, new_part, table_item_size); + + table_num++; + }; + + if (table_num == 0) + { + log_e("Partition table NOT found on flash: %s (len: %d) from offset: 0x%08x.", FAL_PART_TABLE_FLASH_DEV_NAME, + FAL_DEV_NAME_MAX, FAL_PART_TABLE_END_OFFSET); + goto _exit; + } + else + { + partition_table_len = table_num; + } +#endif /* FAL_PART_HAS_TABLE_CFG */ + + /* check the partition table device exists */ + if (check_and_update_part_cache(partition_table, partition_table_len) != 0) + { + goto _exit; + } + + init_ok = 1; + +_exit: + +#if FAL_DEBUG + fal_show_part_table(); +#endif + +#ifndef FAL_PART_HAS_TABLE_CFG + if (new_part) + { + FAL_FREE(new_part); + } +#endif /* !FAL_PART_HAS_TABLE_CFG */ + + return partition_table_len; +} + +/** + * find the partition by name + * + * @param name partition name + * + * @return != NULL: partition + * NULL: not found + */ +const struct fal_partition *fal_partition_find(const char *name) +{ + assert(init_ok); + + size_t i; + + for (i = 0; i < partition_table_len; i++) + { + if (!strcmp(name, partition_table[i].name)) + { + return &partition_table[i]; + } + } + + return NULL; +} + +static const struct fal_flash_dev *flash_device_find_by_part(const struct fal_partition *part) +{ + assert(part >= partition_table); + assert(part <= &partition_table[partition_table_len - 1]); + + return part_flash_cache[part - partition_table].flash_dev; +} + +/** + * get the partition table + * + * @param len return the partition table length + * + * @return partition table + */ +const struct fal_partition *fal_get_partition_table(size_t *len) +{ + assert(init_ok); + assert(len); + + *len = partition_table_len; + + return partition_table; +} + +/** + * set partition table temporarily + * This setting will modify the partition table temporarily, the setting will be lost after restart. + * + * @param table partition table + * @param len partition table length + */ +void fal_set_partition_table_temp(struct fal_partition *table, size_t len) +{ + assert(init_ok); + assert(table); + + check_and_update_part_cache(table, len); + + partition_table_len = len; + partition_table = table; +} + +/** + * read data from partition + * + * @param part partition + * @param addr relative address for partition + * @param buf read buffer + * @param size read size + * + * @return >= 0: successful read data size + * -1: error + */ +int fal_partition_read(const struct fal_partition *part, uint32_t addr, uint8_t *buf, size_t size) +{ + int ret = 0; + const struct fal_flash_dev *flash_dev = NULL; + + assert(part); + assert(buf); + + if (addr + size > part->len) + { + log_e("Partition read error! Partition address out of bound."); + return -1; + } + + flash_dev = flash_device_find_by_part(part); + if (flash_dev == NULL) + { + log_e("Partition read error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name); + return -1; + } + + ret = flash_dev->ops.read(part->offset + addr, buf, size); + if (ret < 0) + { + log_e("Partition read error! Flash device(%s) read error!", part->flash_name); + } + + return ret; +} + +/** + * write data to partition + * + * @param part partition + * @param addr relative address for partition + * @param buf write buffer + * @param size write size + * + * @return >= 0: successful write data size + * -1: error + */ +int fal_partition_write(const struct fal_partition *part, uint32_t addr, const uint8_t *buf, size_t size) +{ + int ret = 0; + const struct fal_flash_dev *flash_dev = NULL; + + assert(part); + assert(buf); + + if (addr + size > part->len) + { + log_e("Partition write error! Partition address out of bound."); + return -1; + } + + flash_dev = flash_device_find_by_part(part); + if (flash_dev == NULL) + { + log_e("Partition write error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name); + return -1; + } + + ret = flash_dev->ops.write(part->offset + addr, buf, size); + if (ret < 0) + { + log_e("Partition write error! Flash device(%s) write error!", part->flash_name); + } + + return ret; +} + +/** + * erase partition data + * + * @param part partition + * @param addr relative address for partition + * @param size erase size + * + * @return >= 0: successful erased data size + * -1: error + */ +int fal_partition_erase(const struct fal_partition *part, uint32_t addr, size_t size) +{ + int ret = 0; + const struct fal_flash_dev *flash_dev = NULL; + + assert(part); + + if (addr + size > part->len) + { + log_e("Partition erase error! Partition address out of bound."); + return -1; + } + + flash_dev = flash_device_find_by_part(part); + if (flash_dev == NULL) + { + log_e("Partition erase error! Don't found flash device(%s) of the partition(%s).", part->flash_name, part->name); + return -1; + } + + ret = flash_dev->ops.erase(part->offset + addr, size); + if (ret < 0) + { + log_e("Partition erase error! Flash device(%s) erase error!", part->flash_name); + } + + return ret; +} + +/** + * erase partition all data + * + * @param part partition + * + * @return >= 0: successful erased data size + * -1: error + */ +int fal_partition_erase_all(const struct fal_partition *part) +{ + return fal_partition_erase(part, 0, part->len); +} diff --git a/User/lib/flashdb/fal/fal_rtt.c b/User/lib/flashdb/fal/fal_rtt.c new file mode 100644 index 0000000..3b699da --- /dev/null +++ b/User/lib/flashdb/fal/fal_rtt.c @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-06-23 armink the first version + * 2019-08-22 MurphyZhao adapt to none rt-thread case + */ + +#include + +#ifdef RT_VER_NUM +#include +#include +#include + +/* ========================== block device ======================== */ +struct fal_blk_device +{ + struct rt_device parent; + struct rt_device_blk_geometry geometry; + const struct fal_partition *fal_part; +}; + +/* RT-Thread device interface */ +#if RTTHREAD_VERSION >= 30000 +static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args) +#else +static rt_err_t blk_dev_control(rt_device_t dev, rt_uint8_t cmd, void *args) +#endif +{ + struct fal_blk_device *part = (struct fal_blk_device*) dev; + + assert(part != RT_NULL); + + if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME) + { + struct rt_device_blk_geometry *geometry; + + geometry = (struct rt_device_blk_geometry *) args; + if (geometry == RT_NULL) + { + return -RT_ERROR; + } + + memcpy(geometry, &part->geometry, sizeof(struct rt_device_blk_geometry)); + } + else if (cmd == RT_DEVICE_CTRL_BLK_ERASE) + { + rt_uint32_t *addrs = (rt_uint32_t *) args, start_addr = addrs[0], end_addr = addrs[1], phy_start_addr; + rt_size_t phy_size; + + if (addrs == RT_NULL || start_addr > end_addr) + { + return -RT_ERROR; + } + + if (end_addr == start_addr) + { + end_addr++; + } + + phy_start_addr = start_addr * part->geometry.bytes_per_sector; + phy_size = (end_addr - start_addr) * part->geometry.bytes_per_sector; + + if (fal_partition_erase(part->fal_part, phy_start_addr, phy_size) < 0) + { + return -RT_ERROR; + } + } + + return RT_EOK; +} + +static rt_size_t blk_dev_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + int ret = 0; + struct fal_blk_device *part = (struct fal_blk_device*) dev; + + assert(part != RT_NULL); + + ret = fal_partition_read(part->fal_part, pos * part->geometry.block_size, buffer, size * part->geometry.block_size); + + if (ret != (int)(size * part->geometry.block_size)) + { + ret = 0; + } + else + { + ret = size; + } + + return ret; +} + +static rt_size_t blk_dev_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +{ + int ret = 0; + struct fal_blk_device *part; + rt_off_t phy_pos; + rt_size_t phy_size; + + part = (struct fal_blk_device*) dev; + assert(part != RT_NULL); + + /* change the block device's logic address to physical address */ + phy_pos = pos * part->geometry.bytes_per_sector; + phy_size = size * part->geometry.bytes_per_sector; + + ret = fal_partition_erase(part->fal_part, phy_pos, phy_size); + + if (ret == (int) phy_size) + { + ret = fal_partition_write(part->fal_part, phy_pos, buffer, phy_size); + } + + if (ret != (int) phy_size) + { + ret = 0; + } + else + { + ret = size; + } + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops blk_dev_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + blk_dev_read, + blk_dev_write, + blk_dev_control +}; +#endif + +/** + * create RT-Thread block device by specified partition + * + * @param parition_name partition name + * + * @return != NULL: created block device + * NULL: created failed + */ +struct rt_device *fal_blk_device_create(const char *parition_name) +{ + struct fal_blk_device *blk_dev; + const struct fal_partition *fal_part = fal_partition_find(parition_name); + const struct fal_flash_dev *fal_flash = NULL; + + if (!fal_part) + { + log_e("Error: the partition name (%s) is not found.", parition_name); + return NULL; + } + + if ((fal_flash = fal_flash_device_find(fal_part->flash_name)) == NULL) + { + log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name); + return NULL; + } + + blk_dev = (struct fal_blk_device*) rt_malloc(sizeof(struct fal_blk_device)); + if (blk_dev) + { + blk_dev->fal_part = fal_part; + blk_dev->geometry.bytes_per_sector = fal_flash->blk_size; + blk_dev->geometry.block_size = fal_flash->blk_size; + blk_dev->geometry.sector_count = fal_part->len / fal_flash->blk_size; + + /* register device */ + blk_dev->parent.type = RT_Device_Class_Block; + +#ifdef RT_USING_DEVICE_OPS + blk_dev->parent.ops = &blk_dev_ops; +#else + blk_dev->parent.init = NULL; + blk_dev->parent.open = NULL; + blk_dev->parent.close = NULL; + blk_dev->parent.read = blk_dev_read; + blk_dev->parent.write = blk_dev_write; + blk_dev->parent.control = blk_dev_control; +#endif + + /* no private */ + blk_dev->parent.user_data = RT_NULL; + + log_i("The FAL block device (%s) created successfully", fal_part->name); + rt_device_register(RT_DEVICE(blk_dev), fal_part->name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); + } + else + { + log_e("Error: no memory for create FAL block device"); + } + + return RT_DEVICE(blk_dev); +} + +/* ========================== MTD nor device ======================== */ +#if defined(RT_USING_MTD_NOR) + +struct fal_mtd_nor_device +{ + struct rt_mtd_nor_device parent; + const struct fal_partition *fal_part; +}; + +static rt_size_t mtd_nor_dev_read(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint8_t* data, rt_uint32_t length) +{ + int ret = 0; + struct fal_mtd_nor_device *part = (struct fal_mtd_nor_device*) device; + + assert(part != RT_NULL); + + ret = fal_partition_read(part->fal_part, offset, data, length); + + if (ret != (int)length) + { + ret = 0; + } + else + { + ret = length; + } + + return ret; +} + +static rt_size_t mtd_nor_dev_write(struct rt_mtd_nor_device* device, rt_off_t offset, const rt_uint8_t* data, rt_uint32_t length) +{ + int ret = 0; + struct fal_mtd_nor_device *part; + + part = (struct fal_mtd_nor_device*) device; + assert(part != RT_NULL); + + ret = fal_partition_write(part->fal_part, offset, data, length); + + if (ret != (int) length) + { + ret = 0; + } + else + { + ret = length; + } + + return ret; +} + +static rt_err_t mtd_nor_dev_erase(struct rt_mtd_nor_device* device, rt_off_t offset, rt_uint32_t length) +{ + int ret = 0; + struct fal_mtd_nor_device *part; + + part = (struct fal_mtd_nor_device*) device; + assert(part != RT_NULL); + + ret = fal_partition_erase(part->fal_part, offset, length); + + if (ret != length) + { + return -RT_ERROR; + } + else + { + return RT_EOK; + } +} + +static const struct rt_mtd_nor_driver_ops _ops = +{ + RT_NULL, + mtd_nor_dev_read, + mtd_nor_dev_write, + mtd_nor_dev_erase, +}; + +/** + * create RT-Thread MTD NOR device by specified partition + * + * @param parition_name partition name + * + * @return != NULL: created MTD NOR device + * NULL: created failed + */ +struct rt_device *fal_mtd_nor_device_create(const char *parition_name) +{ + struct fal_mtd_nor_device *mtd_nor_dev; + const struct fal_partition *fal_part = fal_partition_find(parition_name); + const struct fal_flash_dev *fal_flash = NULL; + + if (!fal_part) + { + log_e("Error: the partition name (%s) is not found.", parition_name); + return NULL; + } + + if ((fal_flash = fal_flash_device_find(fal_part->flash_name)) == NULL) + { + log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name); + return NULL; + } + + mtd_nor_dev = (struct fal_mtd_nor_device*) rt_malloc(sizeof(struct fal_mtd_nor_device)); + if (mtd_nor_dev) + { + mtd_nor_dev->fal_part = fal_part; + + mtd_nor_dev->parent.block_start = 0; + mtd_nor_dev->parent.block_end = fal_part->len / fal_flash->blk_size; + mtd_nor_dev->parent.block_size = fal_flash->blk_size; + + /* set ops */ + mtd_nor_dev->parent.ops = &_ops; + + log_i("The FAL MTD NOR device (%s) created successfully", fal_part->name); + rt_mtd_nor_register_device(fal_part->name, &mtd_nor_dev->parent); + } + else + { + log_e("Error: no memory for create FAL MTD NOR device"); + } + + return RT_DEVICE(&mtd_nor_dev->parent); +} + +#endif /* defined(RT_USING_MTD_NOR) */ + + +/* ========================== char device ======================== */ +struct fal_char_device +{ + struct rt_device parent; + const struct fal_partition *fal_part; +}; + +/* RT-Thread device interface */ +static rt_size_t char_dev_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + int ret = 0; + struct fal_char_device *part = (struct fal_char_device *) dev; + + assert(part != RT_NULL); + + if (pos + size > part->fal_part->len) + size = part->fal_part->len - pos; + + ret = fal_partition_read(part->fal_part, pos, buffer, size); + + if (ret != (int)(size)) + ret = 0; + + return ret; +} + +static rt_size_t char_dev_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + int ret = 0; + struct fal_char_device *part; + + part = (struct fal_char_device *) dev; + assert(part != RT_NULL); + + if (pos == 0) + { + fal_partition_erase_all(part->fal_part); + } + else if (pos + size > part->fal_part->len) + { + size = part->fal_part->len - pos; + } + + ret = fal_partition_write(part->fal_part, pos, buffer, size); + + if (ret != (int) size) + ret = 0; + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops char_dev_ops = +{ + RT_NULL, + RT_NULL, + RT_NULL, + char_dev_read, + char_dev_write, + RT_NULL +}; +#endif + +#ifdef RT_USING_POSIX +#include + +/* RT-Thread device filesystem interface */ +static int char_dev_fopen(struct dfs_fd *fd) +{ + struct fal_char_device *part = (struct fal_char_device *) fd->data; + + assert(part != RT_NULL); + + switch (fd->flags & O_ACCMODE) + { + case O_RDONLY: + break; + case O_WRONLY: + case O_RDWR: + /* erase partition when device file open */ + fal_partition_erase_all(part->fal_part); + break; + default: + break; + } + fd->pos = 0; + + return RT_EOK; +} + +static int char_dev_fread(struct dfs_fd *fd, void *buf, size_t count) +{ + int ret = 0; + struct fal_char_device *part = (struct fal_char_device *) fd->data; + + assert(part != RT_NULL); + + if (fd->pos + count > part->fal_part->len) + count = part->fal_part->len - fd->pos; + + ret = fal_partition_read(part->fal_part, fd->pos, buf, count); + + if (ret != (int)(count)) + return 0; + + fd->pos += ret; + + return ret; +} + +static int char_dev_fwrite(struct dfs_fd *fd, const void *buf, size_t count) +{ + int ret = 0; + struct fal_char_device *part = (struct fal_char_device *) fd->data; + + assert(part != RT_NULL); + + if (fd->pos + count > part->fal_part->len) + count = part->fal_part->len - fd->pos; + + ret = fal_partition_write(part->fal_part, fd->pos, buf, count); + + if (ret != (int) count) + return 0; + + fd->pos += ret; + + return ret; +} + +static const struct dfs_file_ops char_dev_fops = +{ + char_dev_fopen, + RT_NULL, + RT_NULL, + char_dev_fread, + char_dev_fwrite, + RT_NULL, /* flush */ + RT_NULL, /* lseek */ + RT_NULL, /* getdents */ + RT_NULL, +}; +#endif /* defined(RT_USING_POSIX) */ + +/** + * create RT-Thread char device by specified partition + * + * @param parition_name partition name + * + * @return != NULL: created char device + * NULL: created failed + */ +struct rt_device *fal_char_device_create(const char *parition_name) +{ + struct fal_char_device *char_dev; + const struct fal_partition *fal_part = fal_partition_find(parition_name); + + if (!fal_part) + { + log_e("Error: the partition name (%s) is not found.", parition_name); + return NULL; + } + + if ((fal_flash_device_find(fal_part->flash_name)) == NULL) + { + log_e("Error: the flash device name (%s) is not found.", fal_part->flash_name); + return NULL; + } + + char_dev = (struct fal_char_device *) rt_malloc(sizeof(struct fal_char_device)); + if (char_dev) + { + char_dev->fal_part = fal_part; + + /* register device */ + char_dev->parent.type = RT_Device_Class_Char; + +#ifdef RT_USING_DEVICE_OPS + char_dev->parent.ops = &char_dev_ops; +#else + char_dev->parent.init = NULL; + char_dev->parent.open = NULL; + char_dev->parent.close = NULL; + char_dev->parent.read = char_dev_read; + char_dev->parent.write = char_dev_write; + char_dev->parent.control = NULL; + /* no private */ + char_dev->parent.user_data = NULL; +#endif + + rt_device_register(RT_DEVICE(char_dev), fal_part->name, RT_DEVICE_FLAG_RDWR); + log_i("The FAL char device (%s) created successfully", fal_part->name); + +#ifdef RT_USING_POSIX + /* set fops */ + char_dev->parent.fops = &char_dev_fops; +#endif + + } + else + { + log_e("Error: no memory for create FAL char device"); + } + + return RT_DEVICE(char_dev); +} + +#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) + +#include +extern int fal_init_check(void); + +static void fal(uint8_t argc, char **argv) { + +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') +#define HEXDUMP_WIDTH 16 +#define CMD_PROBE_INDEX 0 +#define CMD_READ_INDEX 1 +#define CMD_WRITE_INDEX 2 +#define CMD_ERASE_INDEX 3 +#define CMD_BENCH_INDEX 4 + + int result; + static const struct fal_flash_dev *flash_dev = NULL; + static const struct fal_partition *part_dev = NULL; + size_t i = 0, j = 0; + + const char* help_info[] = + { + [CMD_PROBE_INDEX] = "fal probe [dev_name|part_name] - probe flash device or partition by given name", + [CMD_READ_INDEX] = "fal read addr size - read 'size' bytes starting at 'addr'", + [CMD_WRITE_INDEX] = "fal write addr data1 ... dataN - write some bytes 'data' starting at 'addr'", + [CMD_ERASE_INDEX] = "fal erase addr size - erase 'size' bytes starting at 'addr'", + [CMD_BENCH_INDEX] = "fal bench - benchmark test with per block size", + }; + + if (fal_init_check() != 1) + { + rt_kprintf("\n[Warning] FAL is not initialized or failed to initialize!\n\n"); + return; + } + + if (argc < 2) + { + rt_kprintf("Usage:\n"); + for (i = 0; i < sizeof(help_info) / sizeof(char*); i++) + { + rt_kprintf("%s\n", help_info[i]); + } + rt_kprintf("\n"); + } + else + { + const char *operator = argv[1]; + uint32_t addr, size; + + if (!strcmp(operator, "probe")) + { + if (argc >= 3) + { + char *dev_name = argv[2]; + if ((flash_dev = fal_flash_device_find(dev_name)) != NULL) + { + part_dev = NULL; + } + else if ((part_dev = fal_partition_find(dev_name)) != NULL) + { + flash_dev = NULL; + } + else + { + rt_kprintf("Device %s NOT found. Probe failed.\n", dev_name); + flash_dev = NULL; + part_dev = NULL; + } + } + + if (flash_dev) + { + rt_kprintf("Probed a flash device | %s | addr: %ld | len: %d |.\n", flash_dev->name, + flash_dev->addr, flash_dev->len); + } + else if (part_dev) + { + rt_kprintf("Probed a flash partition | %s | flash_dev: %s | offset: %ld | len: %d |.\n", + part_dev->name, part_dev->flash_name, part_dev->offset, part_dev->len); + } + else + { + rt_kprintf("No flash device or partition was probed.\n"); + rt_kprintf("Usage: %s.\n", help_info[CMD_PROBE_INDEX]); + fal_show_part_table(); + } + } + else + { + if (!flash_dev && !part_dev) + { + rt_kprintf("No flash device or partition was probed. Please run 'fal probe'.\n"); + return; + } + if (!rt_strcmp(operator, "read")) + { + if (argc < 4) + { + rt_kprintf("Usage: %s.\n", help_info[CMD_READ_INDEX]); + return; + } + else + { + addr = strtol(argv[2], NULL, 0); + size = strtol(argv[3], NULL, 0); + uint8_t *data = rt_malloc(size); + if (data) + { + if (flash_dev) + { + result = flash_dev->ops.read(addr, data, size); + } + else if (part_dev) + { + result = fal_partition_read(part_dev, addr, data, size); + } + if (result >= 0) + { + rt_kprintf("Read data success. Start from 0x%08X, size is %ld. The data is:\n", addr, + size); + rt_kprintf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n"); + for (i = 0; i < size; i += HEXDUMP_WIDTH) + { + rt_kprintf("[%08X] ", addr + i); + /* dump hex */ + for (j = 0; j < HEXDUMP_WIDTH; j++) + { + if (i + j < size) + { + rt_kprintf("%02X ", data[i + j]); + } + else + { + rt_kprintf(" "); + } + } + /* dump char for hex */ + for (j = 0; j < HEXDUMP_WIDTH; j++) + { + if (i + j < size) + { + rt_kprintf("%c", __is_print(data[i + j]) ? data[i + j] : '.'); + } + } + rt_kprintf("\n"); + } + rt_kprintf("\n"); + } + rt_free(data); + } + else + { + rt_kprintf("Low memory!\n"); + } + } + } + else if (!strcmp(operator, "write")) + { + if (argc < 4) + { + rt_kprintf("Usage: %s.\n", help_info[CMD_WRITE_INDEX]); + return; + } + else + { + addr = strtol(argv[2], NULL, 0); + size = argc - 3; + uint8_t *data = rt_malloc(size); + if (data) + { + for (i = 0; i < size; i++) + { + data[i] = strtol(argv[3 + i], NULL, 0); + } + if (flash_dev) + { + result = flash_dev->ops.write(addr, data, size); + } + else if (part_dev) + { + result = fal_partition_write(part_dev, addr, data, size); + } + if (result >= 0) + { + rt_kprintf("Write data success. Start from 0x%08X, size is %ld.\n", addr, size); + rt_kprintf("Write data: "); + for (i = 0; i < size; i++) + { + rt_kprintf("%d ", data[i]); + } + rt_kprintf(".\n"); + } + rt_free(data); + } + else + { + rt_kprintf("Low memory!\n"); + } + } + } + else if (!rt_strcmp(operator, "erase")) + { + if (argc < 4) + { + rt_kprintf("Usage: %s.\n", help_info[CMD_ERASE_INDEX]); + return; + } + else + { + addr = strtol(argv[2], NULL, 0); + size = strtol(argv[3], NULL, 0); + if (flash_dev) + { + result = flash_dev->ops.erase(addr, size); + } + else if (part_dev) + { + result = fal_partition_erase(part_dev, addr, size); + } + if (result >= 0) + { + rt_kprintf("Erase data success. Start from 0x%08X, size is %ld.\n", addr, size); + } + } + } + else if (!strcmp(operator, "bench")) + { + if (argc < 3) + { + rt_kprintf("Usage: %s.\n", help_info[CMD_BENCH_INDEX]); + return; + } + else if ((argc > 3 && strcmp(argv[3], "yes")) || argc < 4) + { + rt_kprintf("DANGER: It will erase full chip or partition! Please run 'fal bench %d yes'.\n", strtol(argv[2], NULL, 0)); + return; + } + /* full chip benchmark test */ + uint32_t start_time, time_cast; + size_t write_size = strtol(argv[2], NULL, 0), read_size = strtol(argv[2], NULL, 0), cur_op_size; + uint8_t *write_data = (uint8_t *)rt_malloc(write_size), *read_data = (uint8_t *)rt_malloc(read_size); + + if (write_data && read_data) + { + for (i = 0; i < write_size; i ++) { + write_data[i] = i & 0xFF; + } + if (flash_dev) + { + size = flash_dev->len; + } + else if (part_dev) + { + size = part_dev->len; + } + /* benchmark testing */ + rt_kprintf("Erasing %ld bytes data, waiting...\n", size); + start_time = rt_tick_get(); + if (flash_dev) + { + result = flash_dev->ops.erase(0, size); + } + else if (part_dev) + { + result = fal_partition_erase(part_dev, 0, size); + } + if (result >= 0) + { + time_cast = rt_tick_get() - start_time; + rt_kprintf("Erase benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND, + time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000)); + } + else + { + rt_kprintf("Erase benchmark has an error. Error code: %d.\n", result); + } + /* write test */ + rt_kprintf("Writing %ld bytes data, waiting...\n", size); + start_time = rt_tick_get(); + for (i = 0; i < size; i += write_size) + { + if (i + write_size <= size) + { + cur_op_size = write_size; + } + else + { + cur_op_size = size - i; + } + if (flash_dev) + { + result = flash_dev->ops.write(i, write_data, cur_op_size); + } + else if (part_dev) + { + result = fal_partition_write(part_dev, i, write_data, cur_op_size); + } + if (result < 0) + { + break; + } + } + if (result >= 0) + { + time_cast = rt_tick_get() - start_time; + rt_kprintf("Write benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND, + time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000)); + } + else + { + rt_kprintf("Write benchmark has an error. Error code: %d.\n", result); + } + /* read test */ + rt_kprintf("Reading %ld bytes data, waiting...\n", size); + start_time = rt_tick_get(); + for (i = 0; i < size; i += read_size) + { + if (i + read_size <= size) + { + cur_op_size = read_size; + } + else + { + cur_op_size = size - i; + } + if (flash_dev) + { + result = flash_dev->ops.read(i, read_data, cur_op_size); + } + else if (part_dev) + { + result = fal_partition_read(part_dev, i, read_data, cur_op_size); + } + /* data check */ + for (int index = 0; index < cur_op_size; index ++) + { + if (write_data[index] != read_data[index]) + { + rt_kprintf("%d %d %02x %02x.\n", i, index, write_data[index], read_data[index]); + } + } + + if (memcmp(write_data, read_data, cur_op_size)) + { + result = -RT_ERROR; + rt_kprintf("Data check ERROR! Please check you flash by other command.\n"); + } + /* has an error */ + if (result < 0) + { + break; + } + } + if (result >= 0) + { + time_cast = rt_tick_get() - start_time; + rt_kprintf("Read benchmark success, total time: %d.%03dS.\n", time_cast / RT_TICK_PER_SECOND, + time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000)); + } + else + { + rt_kprintf("Read benchmark has an error. Error code: %d.\n", result); + } + } + else + { + rt_kprintf("Low memory!\n"); + } + rt_free(write_data); + rt_free(read_data); + } + else + { + rt_kprintf("Usage:\n"); + for (i = 0; i < sizeof(help_info) / sizeof(char*); i++) + { + rt_kprintf("%s\n", help_info[i]); + } + rt_kprintf("\n"); + return; + } + if (result < 0) { + rt_kprintf("This operate has an error. Error code: %d.\n", result); + } + } + } +} +MSH_CMD_EXPORT(fal, FAL (Flash Abstraction Layer) operate.); + +#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */ +#endif /* RT_VER_NUM */ diff --git a/User/lib/flashdb/fal_eeprom24_port.c b/User/lib/flashdb/fal_eeprom24_port.c new file mode 100644 index 0000000..8d56c31 --- /dev/null +++ b/User/lib/flashdb/fal_eeprom24_port.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-01-26 armink the first version + */ +#include "eeprom_fm24.h" +#include + +static int init(void); +static int erase(long offset, size_t size); + +static int read(long offset, uint8_t *buf, size_t size); +static int write(long offset, const uint8_t *buf, size_t size); + +// 1.定义 flash 设备 +struct fal_flash_dev eeprom_fm24 = + { + .name = EEPROM_FM24_DEV_NAME, + .addr = 0x000000, + .len = EEPROM_FM24_SIZE, + .blk_size = EEPROM_FM24_BLOCK_SIZE, + .ops = {init, read, write, erase}, + .write_gran = 8}; + +static int init(void) +{ + return 1; +} + +static int erase(long offset, size_t size) +{ + return size; +} + +static int read(long offset, uint8_t *buf, size_t size) +{ + /* You can add your code under here. */ + uint32_t addr = eeprom_fm24.addr + offset; + BOOL res = eeprom_fm24_read(addr, buf, size); + return res == TRUE ? size : 0; +} + +static int write(long offset, const uint8_t *buf, size_t size) +{ + uint32_t addr = eeprom_fm24.addr + offset; + eeprom_fm24_write(addr, (uint8_t *)buf, size); + return size; +} diff --git a/User/lib/flashdb/fal_eeprom95_port.c b/User/lib/flashdb/fal_eeprom95_port.c new file mode 100644 index 0000000..5727697 --- /dev/null +++ b/User/lib/flashdb/fal_eeprom95_port.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-01-26 armink the first version + */ +#include "eeprom_m95.h" +#include + +static int init(void); +static int erase(long offset, size_t size); + +static int read1(long offset, uint8_t *buf, size_t size); +static int write1(long offset, const uint8_t *buf, size_t size); + +static int read2(long offset, uint8_t *buf, size_t size); +static int write2(long offset, const uint8_t *buf, size_t size); + +// 1.定义 flash 设备 +struct fal_flash_dev eeprom_m95_1 = + { + .name = EEPROM_M95_1_DEV_NAME, + .addr = 0x000000, + .len = EEPROM_M95_1_SIZE, + .blk_size = EEPROM_M95_1_BLOCK_SIZE, + .ops = {init, read1, write1, erase}, + .write_gran = 8}; // 设置写粒度,单位 bit, 0 表示未生效(默认值为 0 ),该成员是 fal 版本大于 0.4.0 的新增成员。各个 flash 写入粒度不尽相同,可通过该成员进行设置,以下列举几种常见 Flash 写粒度 + +struct fal_flash_dev eeprom_m95_2 = + { + .name = EEPROM_M95_2_DEV_NAME, + .addr = 0x000000, + .len = EEPROM_M95_2_SIZE, + .blk_size = EEPROM_M95_2_BLOCK_SIZE, + .ops = {init, read2, write2, erase}, + .write_gran = 8}; + +static int init(void) +{ + return 1; +} + +static int erase(long offset, size_t size) +{ + __NOP(); + return size; +} + +static int read1(long offset, uint8_t *buf, size_t size) +{ + /* You can add your code under here. */ + uint32_t addr = eeprom_m95_1.addr + offset; + eeprom_m95_read(M95_1, addr, buf, size); + return size; +} + +static int write1(long offset, const uint8_t *buf, size_t size) +{ + uint32_t addr = eeprom_m95_1.addr + offset; + eeprom_m95_write(M95_1, addr, (uint8_t *)buf, size); + return size; +} + +static int read2(long offset, uint8_t *buf, size_t size) +{ + /* You can add your code under here. */ + uint32_t addr = eeprom_m95_2.addr + offset; + eeprom_m95_read(M95_2, addr, buf, size); + return size; +} + +static int write2(long offset, const uint8_t *buf, size_t size) +{ + uint32_t addr = eeprom_m95_2.addr + offset; + eeprom_m95_write(M95_2, addr, (uint8_t *)buf, size); + return size; +} diff --git a/User/lib/flashdb/fdb.c b/User/lib/flashdb/fdb.c new file mode 100644 index 0000000..021aa90 --- /dev/null +++ b/User/lib/flashdb/fdb.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Initialize interface. + * + * Some initialize interface for this library. + */ + +#include +#include +#include +#include + +#ifdef FDB_USING_FILE_POSIX_MODE +#if !defined(_MSC_VER) +#include +#endif +#endif /* FDB_USING_FILE_POSIX_MODE */ + +#define FDB_LOG_TAG "" + +#if !defined(FDB_USING_FAL_MODE) && !defined(FDB_USING_FILE_MODE) +#error "Please defined the FDB_USING_FAL_MODE or FDB_USING_FILE_MODE macro" +#endif + +fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *path, fdb_db_type type, void *user_data) +{ + FDB_ASSERT(db); + FDB_ASSERT(name); + FDB_ASSERT(path); + + if (db->init_ok) { + return FDB_NO_ERR; + } + + db->name = name; + db->type = type; + db->user_data = user_data; + + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + memset(db->cur_file_sec, FDB_FAILED_ADDR, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file_sec[0])); + /* must set when using file mode */ + FDB_ASSERT(db->sec_size != 0); + FDB_ASSERT(db->max_size != 0); +#ifdef FDB_USING_FILE_POSIX_MODE + memset(db->cur_file, -1, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0])); +#else + memset(db->cur_file, 0, FDB_FILE_CACHE_TABLE_SIZE * sizeof(db->cur_file[0])); +#endif + db->storage.dir = path; + FDB_ASSERT(strlen(path) != 0) +#endif + } else { +#ifdef FDB_USING_FAL_MODE + size_t block_size; + + /* FAL (Flash Abstraction Layer) initialization */ + fal_init(); + /* check the flash partition */ + if ((db->storage.part = fal_partition_find(path)) == NULL) { + FDB_INFO("Error: Partition (%s) not found.\n", path); + return FDB_PART_NOT_FOUND; + } + + block_size = fal_flash_device_find(db->storage.part->flash_name)->blk_size; + if (db->sec_size == 0) { + db->sec_size = block_size; + } else { + /* must be aligned with block size */ + if (db->sec_size % block_size != 0) { + FDB_INFO("Error: db sector size (%" PRIu32 ") MUST align with block size (%" PRIu32 ").\n", db->sec_size, block_size); + return FDB_INIT_FAILED; + } + } + + db->max_size = db->storage.part->len; +#endif /* FDB_USING_FAL_MODE */ + } + + /* the block size MUST to be the Nth power of 2 */ + FDB_ASSERT((db->sec_size & (db->sec_size - 1)) == 0); + /* must align with sector size */ + if (db->max_size % db->sec_size != 0) { + FDB_INFO("Error: db total size (%" PRIu32 ") MUST align with sector size (%" PRIu32 ").\n", db->max_size, db->sec_size); + return FDB_INIT_FAILED; + } + /* must has more than or equal 2 sectors */ + if (db->max_size / db->sec_size < 2) { + FDB_INFO("Error: db MUST has more than or equal 2 sectors, current has %" PRIu32 " sector(s)\n", db->max_size / db->sec_size); + return FDB_INIT_FAILED; + } + + return FDB_NO_ERR; +} + +void _fdb_init_finish(fdb_db_t db, fdb_err_t result) +{ + static bool log_is_show = false; + if (result == FDB_NO_ERR) { + db->init_ok = true; + if (!log_is_show) { + FDB_INFO("FlashDB V%s is initialize success.\n", FDB_SW_VERSION); + FDB_INFO("You can get the latest version on https://github.com/armink/FlashDB .\n"); + log_is_show = true; + } + } else if (!db->not_formatable) { + FDB_INFO("Error: %s (%s@%s) is initialize fail (%d).\n", db->type == FDB_DB_TYPE_KV ? "KVDB" : "TSDB", + db->name, _fdb_db_path(db), (int)result); + } +} + +void _fdb_deinit(fdb_db_t db) +{ + FDB_ASSERT(db); + + if (db->init_ok) { +#ifdef FDB_USING_FILE_MODE + for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) { +#ifdef FDB_USING_FILE_POSIX_MODE + if (db->cur_file[i] > 0) { + close(db->cur_file[i]); + } +#else + if (db->cur_file[i] != 0) { + fclose(db->cur_file[i]); + } +#endif /* FDB_USING_FILE_POSIX_MODE */ + } +#endif /* FDB_USING_FILE_MODE */ + } + + db->init_ok = false; +} + +const char *_fdb_db_path(fdb_db_t db) +{ + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return db->storage.dir; +#else + return NULL; +#endif + } + else { +#ifdef FDB_USING_FAL_MODE + return db->storage.part->name; +#else + return NULL; +#endif + } +} diff --git a/User/lib/flashdb/fdb_cfg.h b/User/lib/flashdb/fdb_cfg.h new file mode 100644 index 0000000..e86aaa7 --- /dev/null +++ b/User/lib/flashdb/fdb_cfg.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief configuration file + */ + +#ifndef _FDB_CFG_H_ +#define _FDB_CFG_H_ + +/* using KVDB feature */ +#define FDB_USING_KVDB + +#ifdef FDB_USING_KVDB +/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */ +#define FDB_KV_AUTO_UPDATE +#endif + +/* using TSDB (Time series database) feature */ +#define FDB_USING_TSDB + +/* Using FAL storage mode */ +#define FDB_USING_FAL_MODE + +#ifdef FDB_USING_FAL_MODE +/* the flash write granularity, unit: bit + * only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1)/ 64(stm32f7)/ 128(stm32h5) */ +#define FDB_WRITE_GRAN 1 /* @note you must define it for a value */ +#endif + +/* Using file storage mode by LIBC file API, like fopen/fread/fwrte/fclose */ +/* #define FDB_USING_FILE_LIBC_MODE */ + +/* Using file storage mode by POSIX file API, like open/read/write/close */ +/* #define FDB_USING_FILE_POSIX_MODE */ + +/* MCU Endian Configuration, default is Little Endian Order. */ +/* #define FDB_BIG_ENDIAN */ + +/* log print macro. default EF_PRINT macro is printf() */ +/* #define FDB_PRINT(...) my_printf(__VA_ARGS__) */ + +/* print debug information */ +#define FDB_DEBUG_ENABLE + +#endif /* _FDB_CFG_H_ */ diff --git a/User/lib/flashdb/fdb_def.h b/User/lib/flashdb/fdb_def.h new file mode 100644 index 0000000..51da4f9 --- /dev/null +++ b/User/lib/flashdb/fdb_def.h @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2020-2023, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public definition. + */ + +#ifndef _FDB_DEF_H_ +#define _FDB_DEF_H_ + +#ifdef FDB_USING_NATIVE_ASSERT +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* software version number */ +#define FDB_SW_VERSION "2.1.0" +#define FDB_SW_VERSION_NUM 0x20100 + +/* the KV max name length must less then it */ +#ifndef FDB_KV_NAME_MAX +#define FDB_KV_NAME_MAX 64 +#endif + +/* the KV cache table size, it will improve KV search speed when using cache */ +#ifndef FDB_KV_CACHE_TABLE_SIZE +#define FDB_KV_CACHE_TABLE_SIZE 64 +#endif + +/* the sector cache table size, it will improve KV save speed when using cache */ +#ifndef FDB_SECTOR_CACHE_TABLE_SIZE +#define FDB_SECTOR_CACHE_TABLE_SIZE 8 +#endif + +#if (FDB_KV_CACHE_TABLE_SIZE > 0) && (FDB_SECTOR_CACHE_TABLE_SIZE > 0) +#define FDB_KV_USING_CACHE +#endif + +#if defined(FDB_USING_FILE_LIBC_MODE) || defined(FDB_USING_FILE_POSIX_MODE) +#define FDB_USING_FILE_MODE +#endif + +/* the file cache table size, it will improve GC speed in file mode when using cache */ +#ifndef FDB_FILE_CACHE_TABLE_SIZE +#define FDB_FILE_CACHE_TABLE_SIZE 6 +#endif + +#ifndef FDB_WRITE_GRAN +#define FDB_WRITE_GRAN 1 +#endif + +/* log function. default FDB_PRINT macro is printf() */ +// #ifndef FDB_PRINT +// #define FDB_PRINT(...) printf(__VA_ARGS__) +// #endif +#ifndef FDB_PRINT +#define FDB_PRINT(...) \ + do \ + { \ + } while (0); +#endif + +#define FDB_LOG_PREFIX1() FDB_PRINT("[FlashDB]" FDB_LOG_TAG) +#define FDB_LOG_PREFIX2() FDB_PRINT(" ") +#define FDB_LOG_PREFIX() \ + FDB_LOG_PREFIX1(); \ + FDB_LOG_PREFIX2() +#ifdef FDB_DEBUG_ENABLE +#define FDB_DEBUG(...) \ + FDB_LOG_PREFIX(); \ + FDB_PRINT("(%s:%d) ", __FILE__, __LINE__); \ + FDB_PRINT(__VA_ARGS__) +#else +#define FDB_DEBUG(...) +#endif +/* routine print function. Must be implement by user. */ +#define FDB_INFO(...) \ + FDB_LOG_PREFIX(); \ + FDB_PRINT(__VA_ARGS__) +/* assert for developer. */ +#ifdef FDB_USING_NATIVE_ASSERT +#define FDB_ASSERT(EXPR) assert(EXPR); +#else +#ifndef FDB_ASSERT +#define FDB_ASSERT(EXPR) \ + if (!(EXPR)) \ + { \ + FDB_INFO("(%s) has assert failed at %s.\n", #EXPR, __func__); \ + while (1) \ + ; \ + } +#endif /* FDB_ASSERT */ +#endif /* FDB_USING_NATIVE_ASSERT */ + +#define FDB_KVDB_CTRL_SET_SEC_SIZE 0x00 /**< set sector size control command, this change MUST before database initialization */ +#define FDB_KVDB_CTRL_GET_SEC_SIZE 0x01 /**< get sector size control command */ +#define FDB_KVDB_CTRL_SET_LOCK 0x02 /**< set lock function control command */ +#define FDB_KVDB_CTRL_SET_UNLOCK 0x03 /**< set unlock function control command */ +#define FDB_KVDB_CTRL_SET_FILE_MODE 0x09 /**< set file mode control command, this change MUST before database initialization */ +#define FDB_KVDB_CTRL_SET_MAX_SIZE 0x0A /**< set database max size in file mode control command, this change MUST before database initialization */ +#define FDB_KVDB_CTRL_SET_NOT_FORMAT 0x0B /**< set database NOT format mode control command, this change MUST before database initialization */ + +#define FDB_TSDB_CTRL_SET_SEC_SIZE 0x00 /**< set sector size control command, this change MUST before database initialization */ +#define FDB_TSDB_CTRL_GET_SEC_SIZE 0x01 /**< get sector size control command */ +#define FDB_TSDB_CTRL_SET_LOCK 0x02 /**< set lock function control command */ +#define FDB_TSDB_CTRL_SET_UNLOCK 0x03 /**< set unlock function control command */ +#define FDB_TSDB_CTRL_SET_ROLLOVER 0x04 /**< set rollover control command, this change MUST after database initialization */ +#define FDB_TSDB_CTRL_GET_ROLLOVER 0x05 /**< get rollover control command */ +#define FDB_TSDB_CTRL_GET_LAST_TIME 0x06 /**< get last save time control command */ +#define FDB_TSDB_CTRL_SET_FILE_MODE 0x09 /**< set file mode control command, this change MUST before database initialization */ +#define FDB_TSDB_CTRL_SET_MAX_SIZE 0x0A /**< set database max size in file mode control command, this change MUST before database initialization */ +#define FDB_TSDB_CTRL_SET_NOT_FORMAT 0x0B /**< set database NOT formatable mode control command, this change MUST before database initialization */ + +#ifdef FDB_USING_TIMESTAMP_64BIT + typedef int64_t fdb_time_t; +#else +typedef int32_t fdb_time_t; +#endif /* FDB_USING_TIMESTAMP_64BIT */ + + typedef fdb_time_t (*fdb_get_time)(void); + + struct fdb_default_kv_node + { + char *key; + void *value; + size_t value_len; + }; + + struct fdb_default_kv + { + struct fdb_default_kv_node *kvs; + size_t num; + }; + typedef struct fdb_default_kv *fdb_default_kv_t; + + /* error code */ + typedef enum + { + FDB_NO_ERR, + FDB_ERASE_ERR, + FDB_READ_ERR, + FDB_WRITE_ERR, + FDB_PART_NOT_FOUND, + FDB_KV_NAME_ERR, + FDB_KV_NAME_EXIST, + FDB_SAVED_FULL, + FDB_INIT_FAILED, + } fdb_err_t; + + enum fdb_kv_status + { + FDB_KV_UNUSED, + FDB_KV_PRE_WRITE, + FDB_KV_WRITE, + FDB_KV_PRE_DELETE, + FDB_KV_DELETED, + FDB_KV_ERR_HDR, +#define FDB_KV_STATUS_NUM 6 + }; + typedef enum fdb_kv_status fdb_kv_status_t; + + enum fdb_tsl_status + { + FDB_TSL_UNUSED, + FDB_TSL_PRE_WRITE, + FDB_TSL_WRITE, + FDB_TSL_USER_STATUS1, + FDB_TSL_DELETED, + FDB_TSL_USER_STATUS2, +#define FDB_TSL_STATUS_NUM 6 + }; + typedef enum fdb_tsl_status fdb_tsl_status_t; + + /* key-value node object */ + struct fdb_kv + { + fdb_kv_status_t status; /**< node status, @see fdb_kv_status_t */ + bool crc_is_ok; /**< node CRC32 check is OK */ + uint8_t name_len; /**< name length */ + uint32_t magic; /**< magic word(`K`, `V`, `4`, `0`) */ + uint32_t len; /**< node total length (header + name + value), must align by FDB_WRITE_GRAN */ + uint32_t value_len; /**< value length */ + char name[FDB_KV_NAME_MAX]; /**< name */ + struct + { + uint32_t start; /**< node start address */ + uint32_t value; /**< value start address */ + } addr; + }; + typedef struct fdb_kv *fdb_kv_t; + + struct fdb_kv_iterator + { + struct fdb_kv curr_kv; /**< Current KV we get from the iterator */ + uint32_t iterated_cnt; /**< How many KVs have we iterated already */ + size_t iterated_obj_bytes; /**< Total storage size of KVs we have iterated. */ + size_t iterated_value_bytes; /**< Total value size of KVs we have iterated. */ + uint32_t sector_addr; /**< Current sector address we're iterating. DO NOT touch it. */ + uint32_t traversed_len; /**< Traversed sector total length. */ + }; + typedef struct fdb_kv_iterator *fdb_kv_iterator_t; + + /* time series log node object */ + struct fdb_tsl + { + fdb_tsl_status_t status; /**< node status, @see fdb_log_status_t */ + fdb_time_t time; /**< node timestamp */ + uint32_t log_len; /**< log length, must align by FDB_WRITE_GRAN */ + struct + { + uint32_t index; /**< node index address */ + uint32_t log; /**< log data address */ + } addr; + }; + typedef struct fdb_tsl *fdb_tsl_t; + typedef bool (*fdb_tsl_cb)(fdb_tsl_t tsl, void *arg); + + typedef enum + { + FDB_DB_TYPE_KV, + FDB_DB_TYPE_TS, + } fdb_db_type; + + /* the flash sector store status */ + enum fdb_sector_store_status + { + FDB_SECTOR_STORE_UNUSED, + FDB_SECTOR_STORE_EMPTY, + FDB_SECTOR_STORE_USING, + FDB_SECTOR_STORE_FULL, +#define FDB_SECTOR_STORE_STATUS_NUM 4 + }; + typedef enum fdb_sector_store_status fdb_sector_store_status_t; + + /* the flash sector dirty status */ + enum fdb_sector_dirty_status + { + FDB_SECTOR_DIRTY_UNUSED, + FDB_SECTOR_DIRTY_FALSE, + FDB_SECTOR_DIRTY_TRUE, + FDB_SECTOR_DIRTY_GC, +#define FDB_SECTOR_DIRTY_STATUS_NUM 4 + }; + typedef enum fdb_sector_dirty_status fdb_sector_dirty_status_t; + + /* KVDB section information */ + struct kvdb_sec_info + { + bool check_ok; /**< sector header check is OK */ + struct + { + fdb_sector_store_status_t store; /**< sector store status @see fdb_sector_store_status_t */ + fdb_sector_dirty_status_t dirty; /**< sector dirty status @see sector_dirty_status_t */ + } status; + uint32_t addr; /**< sector start address */ + uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */ + uint32_t combined; /**< the combined next sector number, 0xFFFFFFFF: not combined */ + size_t remain; /**< remain size */ + uint32_t empty_kv; /**< the next empty KV node start address */ + }; + typedef struct kvdb_sec_info *kv_sec_info_t; + + /* TSDB section information */ + struct tsdb_sec_info + { + bool check_ok; /**< sector header check is OK */ + fdb_sector_store_status_t status; /**< sector store status @see fdb_sector_store_status_t */ + uint32_t addr; /**< sector start address */ + uint32_t magic; /**< magic word(`T`, `S`, `L`, `0`) */ + fdb_time_t start_time; /**< the first start node's timestamp, 0xFFFFFFFF: unused */ + fdb_time_t end_time; /**< the last end node's timestamp, 0xFFFFFFFF: unused */ + uint32_t end_idx; /**< the last end node's index, 0xFFFFFFFF: unused */ + fdb_tsl_status_t end_info_stat[2]; /**< the last end node's info status */ + size_t remain; /**< remain size */ + uint32_t empty_idx; /**< the next empty node index address */ + uint32_t empty_data; /**< the next empty node's data end address */ + }; + typedef struct tsdb_sec_info *tsdb_sec_info_t; + + struct kv_cache_node + { + uint16_t name_crc; /**< KV name's CRC32 low 16bit value */ + uint16_t active; /**< KV node access active degree */ + uint32_t addr; /**< KV node address */ + }; + typedef struct kv_cache_node *kv_cache_node_t; + + /* database structure */ + typedef struct fdb_db *fdb_db_t; + struct fdb_db + { + const char *name; /**< database name */ + fdb_db_type type; /**< database type */ + union + { +#ifdef FDB_USING_FAL_MODE + const struct fal_partition *part; /**< flash partition for saving database */ +#endif +#ifdef FDB_USING_FILE_MODE + const char *dir; /**< directory path for saving database */ +#endif + } storage; + uint32_t sec_size; /**< flash section size. It's a multiple of block size */ + uint32_t max_size; /**< database max size. It's a multiple of section size */ + uint32_t oldest_addr; /**< the oldest sector start address */ + bool init_ok; /**< initialized successfully */ + bool file_mode; /**< is file mode, default is false */ + bool not_formatable; /**< is can NOT be formated mode, default is false */ +#ifdef FDB_USING_FILE_MODE + uint32_t cur_file_sec[FDB_FILE_CACHE_TABLE_SIZE]; /**< last operate sector address */ +#if defined(FDB_USING_FILE_POSIX_MODE) + int cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */ +#elif defined(FDB_USING_FILE_LIBC_MODE) + FILE *cur_file[FDB_FILE_CACHE_TABLE_SIZE]; /**< current file object */ +#endif /* FDB_USING_FILE_MODE */ + uint32_t cur_sec; /**< current operate sector address */ +#endif + void (*lock)(fdb_db_t db); /**< lock the database operate */ + void (*unlock)(fdb_db_t db); /**< unlock the database operate */ + + void *user_data; + }; + + /* KVDB structure */ + struct fdb_kvdb + { + struct fdb_db parent; /**< inherit from fdb_db */ + struct fdb_default_kv default_kvs; /**< default KV */ + bool gc_request; /**< request a GC check */ + bool in_recovery_check; /**< is in recovery check status when first reboot */ + struct fdb_kv cur_kv; + struct kvdb_sec_info cur_sector; + bool last_is_complete_del; + +#ifdef FDB_KV_USING_CACHE + /* KV cache table */ + struct kv_cache_node kv_cache_table[FDB_KV_CACHE_TABLE_SIZE]; + /* sector cache table, it caching the sector info which status is current using */ + struct kvdb_sec_info sector_cache_table[FDB_SECTOR_CACHE_TABLE_SIZE]; +#endif /* FDB_KV_USING_CACHE */ + +#ifdef FDB_KV_AUTO_UPDATE + uint32_t ver_num; /**< setting version number for update */ +#endif + + void *user_data; + }; + typedef struct fdb_kvdb *fdb_kvdb_t; + + /* TSDB structure */ + struct fdb_tsdb + { + struct fdb_db parent; /**< inherit from fdb_db */ + struct tsdb_sec_info cur_sec; /**< current using sector */ + fdb_time_t last_time; /**< last TSL timestamp */ + fdb_get_time get_time; /**< the current timestamp get function */ + size_t max_len; /**< the maximum length of each log */ + bool rollover; /**< the oldest data will rollover by newest data, default is true */ + + void *user_data; + }; + typedef struct fdb_tsdb *fdb_tsdb_t; + + /* blob structure */ + struct fdb_blob + { + void *buf; /**< blob data buffer */ + size_t size; /**< blob data buffer size */ + struct + { + uint32_t meta_addr; /**< saved KV or TSL index address */ + uint32_t addr; /**< blob data saved address */ + size_t len; /**< blob data saved length */ + } saved; + }; + typedef struct fdb_blob *fdb_blob_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _FDB_DEF_H_ */ diff --git a/User/lib/flashdb/fdb_file.c b/User/lib/flashdb/fdb_file.c new file mode 100644 index 0000000..0226122 --- /dev/null +++ b/User/lib/flashdb/fdb_file.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2020, Armink, + * Copyright (c) 2020, enkiller, <462747508@qq.com> + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define FDB_LOG_TAG "[file]" + +#ifdef FDB_USING_FILE_MODE + +#define DB_PATH_MAX 256 + +static void get_db_file_path(fdb_db_t db, uint32_t addr, char *path, size_t size) +{ +#define DB_NAME_MAX 8 + + /* from db_name.fdb.0 to db_name.fdb.n */ + char file_name[DB_NAME_MAX + 4 + 10]; + uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size); + int index = sec_addr / db->sec_size; + + snprintf(file_name, sizeof(file_name), "%.*s.fdb.%d", DB_NAME_MAX, db->name, index); + if (strlen(db->storage.dir) + 1 + strlen(file_name) >= size) { + /* path is too long */ + FDB_INFO("Error: db (%s) file path (%s) is too log.\n", file_name, db->storage.dir); + FDB_ASSERT(0) + } + snprintf(path, size, "%s/%s", db->storage.dir, file_name); +} + +#if defined(FDB_USING_FILE_POSIX_MODE) +#include +#include +#include +#if !defined(_MSC_VER) +#include +#endif + +static int get_file_from_cache(fdb_db_t db, uint32_t sec_addr) +{ + for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) { + if (db->cur_file_sec[i] == sec_addr) + return db->cur_file[i]; + } + + return -1; +} + +static void update_file_cache(fdb_db_t db, uint32_t sec_addr, int fd) +{ + int free_index = FDB_FILE_CACHE_TABLE_SIZE; + + for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) { + if (db->cur_file_sec[i] == sec_addr) { + db->cur_file[i] = fd; + return; + } else if (db->cur_file[i] == -1) { + free_index = i; + } + } + + if (fd > 0) { + if (free_index < FDB_FILE_CACHE_TABLE_SIZE) { + db->cur_file[free_index] = fd; + db->cur_file_sec[free_index] = sec_addr; + } else { + /* cache is full, move to end */ + for (int i = FDB_FILE_CACHE_TABLE_SIZE - 1; i > 0; i--) { + close(db->cur_file[i]); + memcpy(&db->cur_file[i], &db->cur_file[i - 1], sizeof(db->cur_file[0])); + memcpy(&db->cur_file_sec[i], &db->cur_file_sec[i - 1], sizeof(db->cur_file_sec[0])); + } + /* add to head */ + db->cur_file[0] = fd; + db->cur_file_sec[0] = sec_addr; + } + } +} + +static int open_db_file(fdb_db_t db, uint32_t addr, bool clean) +{ + uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size); + int fd = get_file_from_cache(db, sec_addr); + char path[DB_PATH_MAX]; + + if (fd <= 0 || clean) { + get_db_file_path(db, addr, path, DB_PATH_MAX); + + if (fd > 0) { + close(fd); + fd = -1; + update_file_cache(db, sec_addr, fd); + } + if (clean) { + /* clean the old file */ + int clean_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0777); + if (clean_fd <= 0) { + FDB_INFO("Error: open (%s) file failed.\n", path); + } + else { + close(clean_fd); + clean_fd = -1; + } + } + if (get_file_from_cache(db, sec_addr) < 0) { + /* open the database file */ + fd = open(path, O_RDWR, 0777); + update_file_cache(db, sec_addr, fd); + } + db->cur_sec = sec_addr; + } + + return fd; +} + +fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + int fd = open_db_file(db, addr, false); + if (fd > 0) { + /* get the offset address is relative to the start of the current file */ + addr = addr % db->sec_size; + + if ((lseek(fd, addr, SEEK_SET) != (int32_t)addr) || (read(fd, buf, size) != (ssize_t)size)) + result = FDB_READ_ERR; + } else { + result = FDB_READ_ERR; + } + return result; +} + +fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync) +{ + fdb_err_t result = FDB_NO_ERR; + int fd = open_db_file(db, addr, false); + if (fd > 0) { + /* get the offset address is relative to the start of the current file */ + addr = addr % db->sec_size; + + if ((lseek(fd, addr, SEEK_SET) != (int32_t)addr) || (write(fd, buf, size) != (ssize_t)size)) + result = FDB_WRITE_ERR; + if(sync) { + fsync(fd); + } + } else { + result = FDB_WRITE_ERR; + } + return result; +} + +fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + int fd = open_db_file(db, addr, true); + if (fd > 0) { +#define BUF_SIZE 32 + uint8_t buf[BUF_SIZE]; + size_t i; + lseek(fd, 0, SEEK_SET); + for (i = 0; i * BUF_SIZE < size; i++) + { + memset(buf, 0xFF, BUF_SIZE); + write(fd, buf, BUF_SIZE); + } + memset(buf, 0xFF, BUF_SIZE); + write(fd, buf, size - i * BUF_SIZE); + fsync(fd); + } else { + result = FDB_ERASE_ERR; + } + return result; +} +#elif defined(FDB_USING_FILE_LIBC_MODE) + +static FILE *get_file_from_cache(fdb_db_t db, uint32_t sec_addr) +{ + for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) { + if (db->cur_file_sec[i] == sec_addr) + return db->cur_file[i]; + } + + return NULL; +} + +static void update_file_cache(fdb_db_t db, uint32_t sec_addr, FILE *fd) +{ + int free_index = FDB_FILE_CACHE_TABLE_SIZE; + + for (int i = 0; i < FDB_FILE_CACHE_TABLE_SIZE; i++) { + if (db->cur_file_sec[i] == sec_addr) { + db->cur_file[i] = fd; + return; + } + else if (db->cur_file[i] == 0) { + free_index = i; + } + } + + if (fd) { + if (free_index < FDB_FILE_CACHE_TABLE_SIZE) { + db->cur_file[free_index] = fd; + db->cur_file_sec[free_index] = sec_addr; + } + else { + /* cache is full, move to end */ + for (int i = FDB_FILE_CACHE_TABLE_SIZE - 1; i > 0; i--) { + fclose(db->cur_file[i]); + memcpy(&db->cur_file[i], &db->cur_file[i - 1], sizeof(db->cur_file[0])); + memcpy(&db->cur_file_sec[i], &db->cur_file_sec[i - 1], sizeof(db->cur_file_sec[0])); + } + /* add to head */ + db->cur_file[0] = fd; + db->cur_file_sec[0] = sec_addr; + } + } +} + +static FILE *open_db_file(fdb_db_t db, uint32_t addr, bool clean) +{ + uint32_t sec_addr = FDB_ALIGN_DOWN(addr, db->sec_size); + FILE *fd = get_file_from_cache(db, sec_addr); + char path[DB_PATH_MAX]; + + if (fd == NULL || clean) { + get_db_file_path(db, addr, path, DB_PATH_MAX); + + if (fd) { + fclose(fd); + fd = NULL; + update_file_cache(db, sec_addr, fd); + } + + if (clean) { + /* clean the old file */ + FILE *clean_fd = fopen(path, "wb+"); + if (clean_fd == NULL) { + FDB_INFO("Error: open (%s) file failed.\n", path); + } else { + fclose(clean_fd); + clean_fd = NULL; + } + } + if (get_file_from_cache(db, sec_addr) == NULL) { + /* open the database file */ + fd = fopen(path, "rb+"); + update_file_cache(db, sec_addr, fd); + } + db->cur_sec = sec_addr; + } + + return fd; +} + +fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + FILE *fp = open_db_file(db, addr, false); + if (fp) { + addr = addr % db->sec_size; + if ((fseek(fp, addr, SEEK_SET) != 0) || (fread(buf, size, 1, fp) != size)) + result = FDB_READ_ERR; + } else { + result = FDB_READ_ERR; + } + return result; +} + +fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync) +{ + fdb_err_t result = FDB_NO_ERR; + FILE *fp = open_db_file(db, addr, false); + if (fp) { + addr = addr % db->sec_size; + if ((fseek(fp, addr, SEEK_SET) != 0) || (fwrite(buf, size, 1, fp) != size)) + result = FDB_READ_ERR; + if(sync) { + fflush(fp); + } + } else { + result = FDB_READ_ERR; + } + + return result; +} + +fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + + FILE *fp = open_db_file(db, addr, true); + if (fp != NULL) { +#define BUF_SIZE 32 + uint8_t buf[BUF_SIZE]; + size_t i; + fseek(fp, 0, SEEK_SET); + for (i = 0; i * BUF_SIZE < size; i++) + { + memset(buf, 0xFF, BUF_SIZE); + fwrite(buf, BUF_SIZE, 1, fp); + } + memset(buf, 0xFF, BUF_SIZE); + fwrite(buf, size - i * BUF_SIZE, 1, fp); + fflush(fp); + } else { + result = FDB_ERASE_ERR; + } + return result; +} +#endif /* defined(FDB_USING_FILE_LIBC_MODE) */ + +#endif /* FDB_USING_FILE_MODE */ + diff --git a/User/lib/flashdb/fdb_kvdb.c b/User/lib/flashdb/fdb_kvdb.c new file mode 100644 index 0000000..363b28c --- /dev/null +++ b/User/lib/flashdb/fdb_kvdb.c @@ -0,0 +1,2199 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief KVDB feature. + * + * @file fdb_kvdb.c + */ + +#include +#include +#include +#include + +#define FDB_LOG_TAG "[kv]" +/* rewrite log prefix */ +#undef FDB_LOG_PREFIX2 +#define FDB_LOG_PREFIX2() FDB_PRINT("[%s][%s] ", db_name(db), _fdb_db_path((fdb_db_t)db)) + +#if defined(FDB_USING_KVDB) + +#ifndef FDB_WRITE_GRAN +#error "Please configure flash write granularity (in fdb_cfg.h)" +#endif + +#if FDB_WRITE_GRAN != 1 && FDB_WRITE_GRAN != 8 && FDB_WRITE_GRAN != 32 && FDB_WRITE_GRAN != 64 && FDB_WRITE_GRAN != 128 +#error "the write gran can be only setting as 1, 8, 32, 64 and 128" +#endif + +/* magic word(`F`, `D`, `B`, `1`) */ +#define SECTOR_MAGIC_WORD 0x30424446 +/* magic word(`K`, `V`, `0`, `0`) */ +#define KV_MAGIC_WORD 0x3030564B + +/* the sector remain threshold before full status */ +#ifndef FDB_SEC_REMAIN_THRESHOLD +#define FDB_SEC_REMAIN_THRESHOLD (KV_HDR_DATA_SIZE + FDB_KV_NAME_MAX) +#endif + +/* the total remain empty sector threshold before GC */ +#ifndef FDB_GC_EMPTY_SEC_THRESHOLD +#define FDB_GC_EMPTY_SEC_THRESHOLD 6 // https://github.com/armink/FlashDB/issues/156 +#endif + +/* the string KV value buffer size for legacy fdb_get_kv(db, ) function */ +#ifndef FDB_STR_KV_VALUE_MAX_SIZE +#define FDB_STR_KV_VALUE_MAX_SIZE 128 +#endif + +#if FDB_KV_CACHE_TABLE_SIZE > 0xFFFF +#error "The KV cache table size must less than 0xFFFF" +#endif + +/* the sector is not combined value */ +#if (FDB_BYTE_ERASED == 0xFF) +#define SECTOR_NOT_COMBINED 0xFFFFFFFF +#define SECTOR_COMBINED 0x00000000 +#else +#define SECTOR_NOT_COMBINED 0x00000000 +#define SECTOR_COMBINED 0xFFFFFFFF +#endif +/* the next address is get failed */ +#define FAILED_ADDR 0xFFFFFFFF + +#define KV_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_KV_STATUS_NUM) + +#define SECTOR_NUM (db_max_size(db) / db_sec_size(db)) + +#define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data))) +#define SECTOR_STORE_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.store)) +#define SECTOR_DIRTY_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.dirty)) +#define SECTOR_MAGIC_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->magic)) +#define KV_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct kv_hdr_data))) +#define KV_MAGIC_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->magic)) +#define KV_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->len)) +#define KV_NAME_LEN_OFFSET ((unsigned long)(&((struct kv_hdr_data *)0)->name_len)) + +#define db_name(db) (((fdb_db_t)db)->name) +#define db_init_ok(db) (((fdb_db_t)db)->init_ok) +#define db_sec_size(db) (((fdb_db_t)db)->sec_size) +#define db_max_size(db) (((fdb_db_t)db)->max_size) +#define db_oldest_addr(db) (((fdb_db_t)db)->oldest_addr) + +#define db_lock(db) \ + do \ + { \ + if (((fdb_db_t)db)->lock) \ + ((fdb_db_t)db)->lock((fdb_db_t)db); \ + } while (0); + +#define db_unlock(db) \ + do \ + { \ + if (((fdb_db_t)db)->unlock) \ + ((fdb_db_t)db)->unlock((fdb_db_t)db); \ + } while (0); + +#define VER_NUM_KV_NAME "__ver_num__" + +struct sector_hdr_data +{ + struct + { + uint8_t store[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see fdb_sector_store_status_t */ + uint8_t dirty[FDB_DIRTY_STATUS_TABLE_SIZE]; /**< sector dirty status @see fdb_sector_dirty_status_t */ + } status_table; + uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */ + uint32_t combined; /**< the combined next sector number, default: not combined */ + uint32_t reserved; +#if (FDB_WRITE_GRAN == 64) || (FDB_WRITE_GRAN == 128) + uint8_t padding[4]; /**< align padding for 64bit and 128bit write granularity */ +#endif +}; +typedef struct sector_hdr_data *sector_hdr_data_t; + +struct kv_hdr_data +{ + uint8_t status_table[KV_STATUS_TABLE_SIZE]; /**< KV node status, @see fdb_kv_status_t */ + uint32_t magic; /**< magic word(`K`, `V`, `0`, `0`) */ + uint32_t len; /**< KV node total length (header + name + value), must align by FDB_WRITE_GRAN */ + uint32_t crc32; /**< KV node crc32(name_len + data_len + name + value) */ + uint8_t name_len; /**< name length */ + uint32_t value_len; /**< value length */ +#if (FDB_WRITE_GRAN == 64) + uint8_t padding[4]; /**< align padding for 64bit write granularity */ +#endif +#if (FDB_WRITE_GRAN == 128) + uint8_t padding[12]; /**< align padding for 128bit write granularity */ +#endif +}; +typedef struct kv_hdr_data *kv_hdr_data_t; + +struct alloc_kv_cb_args +{ + fdb_kvdb_t db; + size_t kv_size; + uint32_t *empty_kv; +}; + +struct gc_cb_args +{ + fdb_kvdb_t db; + size_t cur_free_size; + size_t setting_free_size; + uint32_t traversed_len; +}; + +static void gc_collect(fdb_kvdb_t db); +static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size); + +#ifdef FDB_KV_USING_CACHE +static void update_sector_cache(fdb_kvdb_t db, kv_sec_info_t sector) +{ + size_t i, empty_index = FDB_SECTOR_CACHE_TABLE_SIZE; + + for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) + { + /* update the sector empty_addr in cache */ + if (db->sector_cache_table[i].addr == sector->addr) + { + if (sector->check_ok) + { + memcpy(&db->sector_cache_table[i], sector, sizeof(struct kvdb_sec_info)); + } + else + { + db->sector_cache_table[i].addr = FDB_DATA_UNUSED; + } + return; + } + else if (db->sector_cache_table[i].addr == FDB_DATA_UNUSED) + { + empty_index = i; + } + } + /* add the sector empty_addr to cache */ + if (sector->check_ok && empty_index < FDB_SECTOR_CACHE_TABLE_SIZE) + { + memcpy(&db->sector_cache_table[empty_index], sector, sizeof(struct kvdb_sec_info)); + } +} + +/* + * Get sector info from cache. It's return true when cache is hit. + */ +static kv_sec_info_t get_sector_from_cache(fdb_kvdb_t db, uint32_t sec_addr) +{ + size_t i; + + for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) + { + if (db->sector_cache_table[i].addr == sec_addr) + { + return &db->sector_cache_table[i]; + } + } + + return NULL; +} + +static void update_sector_empty_addr_cache(fdb_kvdb_t db, uint32_t sec_addr, uint32_t empty_addr) +{ + kv_sec_info_t sector = get_sector_from_cache(db, sec_addr); + if (sector) + { + sector->empty_kv = empty_addr; + sector->remain = db_sec_size(db) - (sector->empty_kv - sector->addr); + } +} + +static void update_sector_status_store_cache(fdb_kvdb_t db, uint32_t sec_addr, fdb_sector_store_status_t stauts) +{ + kv_sec_info_t sector = get_sector_from_cache(db, sec_addr); + if (sector) + { + sector->status.store = stauts; + } +} + +static void update_kv_cache(fdb_kvdb_t db, const char *name, size_t name_len, uint32_t addr) +{ + size_t i, empty_index = FDB_KV_CACHE_TABLE_SIZE, min_activity_index = FDB_KV_CACHE_TABLE_SIZE; + uint16_t name_crc = (uint16_t)(fdb_calc_crc32(0, name, name_len) >> 16), min_activity = 0xFFFF; + + for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) + { + if (addr != FDB_DATA_UNUSED) + { + /* update the KV address in cache */ + if (db->kv_cache_table[i].name_crc == name_crc) + { + db->kv_cache_table[i].addr = addr; + return; + } + else if ((db->kv_cache_table[i].addr == FDB_DATA_UNUSED) && (empty_index == FDB_KV_CACHE_TABLE_SIZE)) + { + empty_index = i; + } + else if (db->kv_cache_table[i].addr != FDB_DATA_UNUSED) + { + if (db->kv_cache_table[i].active > 0) + { + db->kv_cache_table[i].active--; + } + if (db->kv_cache_table[i].active < min_activity) + { + min_activity_index = i; + min_activity = db->kv_cache_table[i].active; + } + } + } + else if (db->kv_cache_table[i].name_crc == name_crc) + { + /* delete the KV */ + db->kv_cache_table[i].addr = FDB_DATA_UNUSED; + db->kv_cache_table[i].active = 0; + return; + } + } + /* add the KV to cache, using LRU (Least Recently Used) like algorithm */ + if (empty_index < FDB_KV_CACHE_TABLE_SIZE) + { + db->kv_cache_table[empty_index].addr = addr; + db->kv_cache_table[empty_index].name_crc = name_crc; + db->kv_cache_table[empty_index].active = FDB_KV_CACHE_TABLE_SIZE; + } + else if (min_activity_index < FDB_KV_CACHE_TABLE_SIZE) + { + db->kv_cache_table[min_activity_index].addr = addr; + db->kv_cache_table[min_activity_index].name_crc = name_crc; + db->kv_cache_table[min_activity_index].active = FDB_KV_CACHE_TABLE_SIZE; + } +} + +/* + * Get KV info from cache. It's return true when cache is hit. + */ +static bool get_kv_from_cache(fdb_kvdb_t db, const char *name, size_t name_len, uint32_t *addr) +{ + size_t i; + uint16_t name_crc = (uint16_t)(fdb_calc_crc32(0, name, name_len) >> 16); + + for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) + { + if ((db->kv_cache_table[i].addr != FDB_DATA_UNUSED) && (db->kv_cache_table[i].name_crc == name_crc)) + { + char saved_name[FDB_KV_NAME_MAX] = {0}; + /* read the KV name in flash */ + _fdb_flash_read((fdb_db_t)db, db->kv_cache_table[i].addr + KV_HDR_DATA_SIZE, (uint32_t *)saved_name, FDB_KV_NAME_MAX); + if (!strncmp(name, saved_name, name_len)) + { + *addr = db->kv_cache_table[i].addr; + if (db->kv_cache_table[i].active >= 0xFFFF - FDB_KV_CACHE_TABLE_SIZE) + { + db->kv_cache_table[i].active = 0xFFFF; + } + else + { + db->kv_cache_table[i].active += FDB_KV_CACHE_TABLE_SIZE; + } + return true; + } + } + } + + return false; +} +#endif /* FDB_KV_USING_CACHE */ + +/* + * find the next KV address by magic word on the flash + */ +static uint32_t find_next_kv_addr(fdb_kvdb_t db, uint32_t start, uint32_t end) +{ + uint8_t buf[32]; + uint32_t start_bak = start, i; + uint32_t magic; + +#ifdef FDB_KV_USING_CACHE + kv_sec_info_t sector; + sector = get_sector_from_cache(db, FDB_ALIGN_DOWN(start, db_sec_size(db))); + if (sector && start == sector->empty_kv) + { + return FAILED_ADDR; + } +#endif /* FDB_KV_USING_CACHE */ + + for (; start < end && start + sizeof(buf) < end; start += (sizeof(buf) - sizeof(uint32_t))) + { + if (_fdb_flash_read((fdb_db_t)db, start, (uint32_t *)buf, sizeof(buf)) != FDB_NO_ERR) + return FAILED_ADDR; + for (i = 0; i < sizeof(buf) - sizeof(uint32_t) && start + i < end; i++) + { +#ifndef FDB_BIG_ENDIAN /* Little Endian Order */ + magic = buf[i] + (buf[i + 1] << 8) + (buf[i + 2] << 16) + (buf[i + 3] << 24); +#else /* Big Endian Order */ + magic = buf[i + 3] + (buf[i + 2] << 8) + (buf[i + 1] << 16) + (buf[i] << 24); +#endif + if (magic == KV_MAGIC_WORD && (start + i - KV_MAGIC_OFFSET) >= start_bak) + { + return start + i - KV_MAGIC_OFFSET; + } + } + } + + return FAILED_ADDR; +} + +static uint32_t get_next_kv_addr(fdb_kvdb_t db, kv_sec_info_t sector, fdb_kv_t pre_kv) +{ + uint32_t addr = FAILED_ADDR; + + if (sector->status.store == FDB_SECTOR_STORE_EMPTY) + { + return FAILED_ADDR; + } + + if (pre_kv->addr.start == FAILED_ADDR) + { + /* the first KV address */ + addr = sector->addr + SECTOR_HDR_DATA_SIZE; + } + else + { + if (pre_kv->addr.start <= sector->addr + db_sec_size(db)) + { + if (pre_kv->crc_is_ok) + { + addr = pre_kv->addr.start + pre_kv->len; + } + else + { + /* when pre_kv CRC check failed, maybe the flash has error data + * find_next_kv_addr after pre_kv address */ + addr = pre_kv->addr.start + FDB_WG_ALIGN(1); + } + /* check and find next KV address */ + addr = find_next_kv_addr(db, addr, sector->addr + db_sec_size(db) - SECTOR_HDR_DATA_SIZE); + + if (addr == FAILED_ADDR || addr > sector->addr + db_sec_size(db) || pre_kv->len == 0) + { + // TODO Sector continuous mode + return FAILED_ADDR; + } + } + else + { + /* no KV */ + return FAILED_ADDR; + } + } + + return addr; +} + +static fdb_err_t read_kv(fdb_kvdb_t db, fdb_kv_t kv) +{ + struct kv_hdr_data kv_hdr; + uint8_t buf[32]; + uint32_t calc_crc32 = 0, crc_data_len, kv_name_addr; + fdb_err_t result = FDB_NO_ERR; + size_t len, size; + /* read KV header raw data */ + _fdb_flash_read((fdb_db_t)db, kv->addr.start, (uint32_t *)&kv_hdr, sizeof(struct kv_hdr_data)); + kv->status = (fdb_kv_status_t)_fdb_get_status(kv_hdr.status_table, FDB_KV_STATUS_NUM); + kv->len = kv_hdr.len; + + if (kv->len == UINT32_MAX || kv->len > db_max_size(db) || kv->len < KV_HDR_DATA_SIZE) + { + /* the KV length was not write, so reserved the info for current KV */ + kv->len = KV_HDR_DATA_SIZE; + if (kv->status != FDB_KV_ERR_HDR) + { + kv->status = FDB_KV_ERR_HDR; + FDB_INFO("Error: The KV @0x%08" PRIX32 " length has an error.\n", kv->addr.start); + _fdb_write_status((fdb_db_t)db, kv->addr.start, kv_hdr.status_table, FDB_KV_STATUS_NUM, FDB_KV_ERR_HDR, true); + } + kv->crc_is_ok = false; + return FDB_READ_ERR; + } + else if (kv->len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE && kv->len < db_max_size(db)) + { + // TODO Sector continuous mode, or the write length is not written completely + } + + /* CRC32 data len(header.name_len + header.value_len + name + value), using sizeof(uint32_t) for compatible V1.x */ + calc_crc32 = fdb_calc_crc32(calc_crc32, &kv_hdr.name_len, sizeof(uint32_t)); + calc_crc32 = fdb_calc_crc32(calc_crc32, &kv_hdr.value_len, sizeof(uint32_t)); + crc_data_len = kv->len - KV_HDR_DATA_SIZE; + /* calculate the CRC32 value */ + for (len = 0, size = 0; len < crc_data_len; len += size) + { + if (len + sizeof(buf) < crc_data_len) + { + size = sizeof(buf); + } + else + { + size = crc_data_len - len; + } + + _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_HDR_DATA_SIZE + len, (uint32_t *)buf, FDB_WG_ALIGN(size)); + calc_crc32 = fdb_calc_crc32(calc_crc32, buf, size); + } + /* check CRC32 */ + if (calc_crc32 != kv_hdr.crc32) + { + size_t name_len = kv_hdr.name_len > FDB_KV_NAME_MAX ? FDB_KV_NAME_MAX : kv_hdr.name_len; + kv->crc_is_ok = false; + result = FDB_READ_ERR; + /* try read the KV name, maybe read name has error */ + kv_name_addr = kv->addr.start + KV_HDR_DATA_SIZE; + _fdb_flash_read((fdb_db_t)db, kv_name_addr, (uint32_t *)kv->name, FDB_WG_ALIGN(name_len)); + FDB_INFO("Error: Read the KV (%.*s@0x%08" PRIX32 ") CRC32 check failed!\n", name_len, kv->name, kv->addr.start); + } + else + { + kv->crc_is_ok = true; + /* the name is behind aligned KV header */ + kv_name_addr = kv->addr.start + KV_HDR_DATA_SIZE; + _fdb_flash_read((fdb_db_t)db, kv_name_addr, (uint32_t *)kv->name, FDB_WG_ALIGN(kv_hdr.name_len)); + /* the value is behind aligned name */ + kv->addr.value = kv_name_addr + FDB_WG_ALIGN(kv_hdr.name_len); + kv->value_len = kv_hdr.value_len; + kv->name_len = kv_hdr.name_len; + if (kv_hdr.name_len >= sizeof(kv->name) / sizeof(kv->name[0])) + { + kv_hdr.name_len = sizeof(kv->name) / sizeof(kv->name[0]) - 1; + } + kv->name[kv_hdr.name_len] = '\0'; + } + + return result; +} + +static fdb_err_t read_sector_info(fdb_kvdb_t db, uint32_t addr, kv_sec_info_t sector, bool traversal) +{ + fdb_err_t result = FDB_NO_ERR; + struct sector_hdr_data sec_hdr = {0}; + + FDB_ASSERT(addr % db_sec_size(db) == 0); + FDB_ASSERT(sector); + +#ifdef FDB_KV_USING_CACHE + kv_sec_info_t sector_cache = get_sector_from_cache(db, addr); + if (sector_cache && ((!traversal) || (traversal && sector_cache->empty_kv != FAILED_ADDR))) + { + memcpy(sector, sector_cache, sizeof(struct kvdb_sec_info)); + return result; + } +#endif /* FDB_KV_USING_CACHE */ + + /* read sector header raw data */ + _fdb_flash_read((fdb_db_t)db, addr, (uint32_t *)&sec_hdr, sizeof(struct sector_hdr_data)); + + sector->status.store = FDB_SECTOR_STORE_UNUSED; + sector->status.dirty = FDB_SECTOR_DIRTY_UNUSED; + sector->addr = addr; + sector->magic = sec_hdr.magic; + /* check magic word and combined value */ + if (sector->magic != SECTOR_MAGIC_WORD || + (sec_hdr.combined != SECTOR_NOT_COMBINED && sec_hdr.combined != SECTOR_COMBINED)) + { + sector->check_ok = false; + sector->combined = SECTOR_NOT_COMBINED; + return FDB_INIT_FAILED; + } + sector->check_ok = true; + /* get other sector info */ + sector->combined = sec_hdr.combined; + sector->status.store = (fdb_sector_store_status_t)_fdb_get_status(sec_hdr.status_table.store, FDB_SECTOR_STORE_STATUS_NUM); + sector->status.dirty = (fdb_sector_dirty_status_t)_fdb_get_status(sec_hdr.status_table.dirty, FDB_SECTOR_DIRTY_STATUS_NUM); + /* traversal all KV and calculate the remain space size */ + if (traversal) + { + sector->remain = 0; + sector->empty_kv = sector->addr + SECTOR_HDR_DATA_SIZE; + if (sector->status.store == FDB_SECTOR_STORE_EMPTY) + { + sector->remain = db_sec_size(db) - SECTOR_HDR_DATA_SIZE; + } + else if (sector->status.store == FDB_SECTOR_STORE_USING) + { + struct fdb_kv kv_obj; + + sector->remain = db_sec_size(db) - SECTOR_HDR_DATA_SIZE; + kv_obj.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE; + do + { + read_kv(db, &kv_obj); + if (!kv_obj.crc_is_ok) + { + if (kv_obj.status != FDB_KV_PRE_WRITE && kv_obj.status != FDB_KV_ERR_HDR) + { + sector->remain = 0; + result = FDB_READ_ERR; + break; + } + } + sector->empty_kv += kv_obj.len; + sector->remain -= kv_obj.len; + } while ((kv_obj.addr.start = get_next_kv_addr(db, sector, &kv_obj)) != FAILED_ADDR); + /* check the empty KV address by read continue 0xFF on flash */ + { + uint32_t ff_addr; + + ff_addr = _fdb_continue_ff_addr((fdb_db_t)db, sector->empty_kv, sector->addr + db_sec_size(db)); + /* check the flash data is clean */ + if (sector->empty_kv != ff_addr) + { + /* update the sector information */ + sector->empty_kv = ff_addr; + sector->remain = db_sec_size(db) - (ff_addr - sector->addr); + } + } + } +#ifdef FDB_KV_USING_CACHE + update_sector_cache(db, sector); + } + else + { + kv_sec_info_t sector_cache = get_sector_from_cache(db, sector->addr); + if (!sector_cache) + { + sector->empty_kv = FAILED_ADDR; + sector->remain = 0; + update_sector_cache(db, sector); + } +#endif + } + + return result; +} + +static uint32_t get_next_sector_addr(fdb_kvdb_t db, kv_sec_info_t pre_sec, uint32_t traversed_len) +{ + uint32_t cur_block_size; + + if (pre_sec->combined == SECTOR_NOT_COMBINED) + { + cur_block_size = db_sec_size(db); + } + else + { + cur_block_size = pre_sec->combined * db_sec_size(db); + } + + if (traversed_len + cur_block_size <= db_max_size(db)) + { + /* if reach to the end, roll back to the first sector */ + if (pre_sec->addr + cur_block_size < db_max_size(db)) + { + return pre_sec->addr + cur_block_size; + } + else + { + /* the next sector is on the top of the database */ + return 0; + } + } + else + { + /* finished */ + return FAILED_ADDR; + } +} + +static void kv_iterator(fdb_kvdb_t db, fdb_kv_t kv, void *arg1, void *arg2, + bool (*callback)(fdb_kv_t kv, void *arg1, void *arg2)) +{ + struct kvdb_sec_info sector; + uint32_t sec_addr, traversed_len = 0; + + sec_addr = db_oldest_addr(db); + /* search all sectors */ + do + { + traversed_len += db_sec_size(db); + if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) + { + continue; + } + if (callback == NULL) + { + continue; + } + /* sector has KV */ + if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) + { + kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE; + /* search all KV */ + do + { + read_kv(db, kv); + /* iterator is interrupted when callback return true */ + if (callback(kv, arg1, arg2)) + { + return; + } + } while ((kv->addr.start = get_next_kv_addr(db, §or, kv)) != FAILED_ADDR); + } + } while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR); +} + +static bool find_kv_cb(fdb_kv_t kv, void *arg1, void *arg2) +{ + const char *key = arg1; + bool *find_ok = arg2; + size_t key_len = strlen(key); + + if (key_len != kv->name_len) + { + return false; + } + /* check KV */ + if (kv->crc_is_ok && kv->status == FDB_KV_WRITE && !strncmp(kv->name, key, key_len)) + { + *find_ok = true; + return true; + } + return false; +} + +static bool find_kv_no_cache(fdb_kvdb_t db, const char *key, fdb_kv_t kv) +{ + bool find_ok = false; + + kv_iterator(db, kv, (void *)key, &find_ok, find_kv_cb); + + return find_ok; +} + +static bool find_kv(fdb_kvdb_t db, const char *key, fdb_kv_t kv) +{ + bool find_ok = false; + +#ifdef FDB_KV_USING_CACHE + size_t key_len = strlen(key); + + if (get_kv_from_cache(db, key, key_len, &kv->addr.start)) + { + read_kv(db, kv); + return true; + } +#endif /* FDB_KV_USING_CACHE */ + + find_ok = find_kv_no_cache(db, key, kv); + +#ifdef FDB_KV_USING_CACHE + if (find_ok) + { + update_kv_cache(db, key, key_len, kv->addr.start); + } +#endif /* FDB_KV_USING_CACHE */ + + return find_ok; +} + +static bool fdb_is_str(uint8_t *value, size_t len) +{ +#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') + size_t i; + + for (i = 0; i < len; i++) + { + if (!__is_print(value[i])) + { + return false; + } + } + return true; +} + +static size_t get_kv(fdb_kvdb_t db, const char *key, void *value_buf, size_t buf_len, size_t *value_len) +{ + struct fdb_kv kv; + size_t read_len = 0; + + if (find_kv(db, key, &kv)) + { + if (value_len) + { + *value_len = kv.value_len; + } + if (buf_len > kv.value_len) + { + read_len = kv.value_len; + } + else + { + read_len = buf_len; + } + if (value_buf) + { + _fdb_flash_read((fdb_db_t)db, kv.addr.value, (uint32_t *)value_buf, read_len); + } + } + else if (value_len) + { + *value_len = 0; + } + + return read_len; +} + +/** + * Get a KV object by key name + * + * @param db database object + * @param key KV name + * @param kv KV object + * + * @return KV object when is not NULL + */ +fdb_kv_t fdb_kv_get_obj(fdb_kvdb_t db, const char *key, fdb_kv_t kv) +{ + bool find_ok = false; + + if (!db_init_ok(db)) + { + FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db)); + return 0; + } + + /* lock the KV cache */ + db_lock(db); + + find_ok = find_kv(db, key, kv); + + /* unlock the KV cache */ + db_unlock(db); + + return find_ok ? kv : NULL; +} + +/** + * Convert the KV object to blob object + * + * @param kv KV object + * @param blob blob object + * + * @return new blob object + */ +fdb_blob_t fdb_kv_to_blob(fdb_kv_t kv, fdb_blob_t blob) +{ + blob->saved.meta_addr = kv->addr.start; + blob->saved.addr = kv->addr.value; + blob->saved.len = kv->value_len; + + return blob; +} + +/** + * Get a blob KV value by key name. + * + * @param db database object + * @param key KV name + * @param blob blob object + * + * @return the actually get size on successful + */ +size_t fdb_kv_get_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob) +{ + size_t read_len = 0; + + if (!db_init_ok(db)) + { + FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db)); + return 0; + } + + /* lock the KV cache */ + db_lock(db); + + read_len = get_kv(db, key, blob->buf, blob->size, &blob->saved.len); + + /* unlock the KV cache */ + db_unlock(db); + + return read_len; +} + +/** + * Get an KV value by key name. + * + * @note this function is NOT supported reentrant + * @note this function is DEPRECATED + * + * @param db database object + * @param key KV name + * + * @return value + */ +char *fdb_kv_get(fdb_kvdb_t db, const char *key) +{ + static char value[FDB_STR_KV_VALUE_MAX_SIZE + 1]; + size_t get_size; + struct fdb_blob blob; + + if ((get_size = fdb_kv_get_blob(db, key, fdb_blob_make(&blob, value, FDB_STR_KV_VALUE_MAX_SIZE))) > 0) + { + /* the return value must be string */ + if (fdb_is_str((uint8_t *)value, get_size)) + { + value[get_size] = '\0'; + return value; + } + else if (blob.saved.len > FDB_STR_KV_VALUE_MAX_SIZE) + { + FDB_INFO("Warning: The default string KV value buffer length (%" PRIdLEAST16 ") is too less (%" PRIu32 ").\n", FDB_STR_KV_VALUE_MAX_SIZE, + (uint32_t)blob.saved.len); + } + else + { + FDB_INFO("Warning: The KV value isn't string. Could not be returned\n"); + return NULL; + } + } + + return NULL; +} + +static fdb_err_t write_kv_hdr(fdb_kvdb_t db, uint32_t addr, kv_hdr_data_t kv_hdr) +{ + fdb_err_t result = FDB_NO_ERR; + /* write the status will by write granularity */ + result = _fdb_write_status((fdb_db_t)db, addr, kv_hdr->status_table, FDB_KV_STATUS_NUM, FDB_KV_PRE_WRITE, false); + if (result != FDB_NO_ERR) + { + return result; + } + /* write other header data */ + result = _fdb_flash_write((fdb_db_t)db, addr + KV_MAGIC_OFFSET, &kv_hdr->magic, sizeof(struct kv_hdr_data) - KV_MAGIC_OFFSET, false); + + return result; +} + +static fdb_err_t format_sector(fdb_kvdb_t db, uint32_t addr, uint32_t combined_value) +{ + fdb_err_t result = FDB_NO_ERR; + struct sector_hdr_data sec_hdr = {0}; + + FDB_ASSERT(addr % db_sec_size(db) == 0); + + result = _fdb_flash_erase((fdb_db_t)db, addr, db_sec_size(db)); + if (result == FDB_NO_ERR) + { + /* initialize the header data */ + memset(&sec_hdr, FDB_BYTE_ERASED, sizeof(struct sector_hdr_data)); +#if (FDB_WRITE_GRAN == 1) + _fdb_set_status(sec_hdr.status_table.store, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_EMPTY); + _fdb_set_status(sec_hdr.status_table.dirty, FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_FALSE); + sec_hdr.magic = SECTOR_MAGIC_WORD; + sec_hdr.combined = combined_value; + sec_hdr.reserved = FDB_DATA_UNUSED; + /* save the header */ + result = _fdb_flash_write((fdb_db_t)db, addr, (uint32_t *)&sec_hdr, SECTOR_HDR_DATA_SIZE, true); +#else // seperate the whole "sec_hdr" program to serval sinle program operation to prevent re-program issue on STM32L4xx or + // other MCU internal flash + /* write the sector store status */ + _fdb_write_status((fdb_db_t)db, + addr + SECTOR_STORE_OFFSET, + sec_hdr.status_table.store, + FDB_SECTOR_STORE_STATUS_NUM, + FDB_SECTOR_STORE_EMPTY, + true); + + /* write the sector dirty status */ + _fdb_write_status((fdb_db_t)db, + addr + SECTOR_DIRTY_OFFSET, + sec_hdr.status_table.dirty, + FDB_SECTOR_DIRTY_STATUS_NUM, + FDB_SECTOR_DIRTY_FALSE, + true); + + /* write the magic word and combined next sector number */ + sec_hdr.magic = SECTOR_MAGIC_WORD; + sec_hdr.combined = combined_value; + sec_hdr.reserved = FDB_DATA_UNUSED; + result = _fdb_flash_write((fdb_db_t)db, + addr + SECTOR_MAGIC_OFFSET, + (void *)(&(sec_hdr.magic)), + (sizeof(struct sector_hdr_data) - SECTOR_MAGIC_OFFSET), + true); +#endif + +#ifdef FDB_KV_USING_CACHE + { + struct kvdb_sec_info sector = {.addr = addr, .check_ok = false, .empty_kv = FAILED_ADDR}; + /* delete the sector cache */ + update_sector_cache(db, §or); + } +#endif /* FDB_KV_USING_CACHE */ + } + + return result; +} + +static fdb_err_t update_sec_status(fdb_kvdb_t db, kv_sec_info_t sector, size_t new_kv_len, bool *is_full) +{ + uint8_t status_table[FDB_STORE_STATUS_TABLE_SIZE]; + fdb_err_t result = FDB_NO_ERR; + /* change the current sector status */ + if (sector->status.store == FDB_SECTOR_STORE_EMPTY) + { + /* change the sector status to using */ + result = _fdb_write_status((fdb_db_t)db, sector->addr, status_table, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_USING, true); + +#ifdef FDB_KV_USING_CACHE + update_sector_status_store_cache(db, sector->addr, FDB_SECTOR_STORE_USING); +#endif /* FDB_KV_USING_CACHE */ + } + else if (sector->status.store == FDB_SECTOR_STORE_USING) + { + /* check remain size */ + if (sector->remain < FDB_SEC_REMAIN_THRESHOLD || sector->remain - new_kv_len < FDB_SEC_REMAIN_THRESHOLD) + { + /* change the sector status to full */ + result = _fdb_write_status((fdb_db_t)db, sector->addr, status_table, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_FULL, true); + +#ifdef FDB_KV_USING_CACHE + update_sector_status_store_cache(db, sector->addr, FDB_SECTOR_STORE_FULL); +#endif /* FDB_KV_USING_CACHE */ + + if (is_full) + { + *is_full = true; + } + } + else if (is_full) + { + *is_full = false; + } + } + + return result; +} + +static void sector_iterator(fdb_kvdb_t db, kv_sec_info_t sector, fdb_sector_store_status_t status, void *arg1, void *arg2, + bool (*callback)(kv_sec_info_t sector, void *arg1, void *arg2), bool traversal_kv) +{ + uint32_t sec_addr, traversed_len = 0; + + /* search all sectors */ + sec_addr = db_oldest_addr(db); + do + { + traversed_len += db_sec_size(db); + read_sector_info(db, sec_addr, sector, false); + if (status == FDB_SECTOR_STORE_UNUSED || status == sector->status.store) + { + if (traversal_kv) + { + read_sector_info(db, sec_addr, sector, true); + } + /* iterator is interrupted when callback return true */ + if (callback && callback(sector, arg1, arg2)) + { + return; + } + } + } while ((sec_addr = get_next_sector_addr(db, sector, traversed_len)) != FAILED_ADDR); +} + +static bool sector_statistics_cb(kv_sec_info_t sector, void *arg1, void *arg2) +{ + size_t *empty_sector = arg1, *using_sector = arg2; + + if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_EMPTY) + { + (*empty_sector)++; + } + else if (sector->check_ok && sector->status.store == FDB_SECTOR_STORE_USING) + { + (*using_sector)++; + } + + return false; +} + +static bool alloc_kv_cb(kv_sec_info_t sector, void *arg1, void *arg2) +{ + struct alloc_kv_cb_args *arg = arg1; + + /* 1. sector has space + * 2. the NO dirty sector + * 3. the dirty sector only when the gc_request is false */ + if (sector->check_ok && sector->remain > arg->kv_size + FDB_SEC_REMAIN_THRESHOLD && ((sector->status.dirty == FDB_SECTOR_DIRTY_FALSE) || (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE && !arg->db->gc_request))) + { + *(arg->empty_kv) = sector->empty_kv; + return true; + } + + return false; +} + +static uint32_t alloc_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size) +{ + uint32_t empty_kv = FAILED_ADDR; + size_t empty_sector = 0, using_sector = 0; + struct alloc_kv_cb_args arg = {db, kv_size, &empty_kv}; + + /* sector status statistics */ + sector_iterator(db, sector, FDB_SECTOR_STORE_UNUSED, &empty_sector, &using_sector, sector_statistics_cb, false); + if (using_sector > 0) + { + /* alloc the KV from the using status sector first */ + sector_iterator(db, sector, FDB_SECTOR_STORE_USING, &arg, NULL, alloc_kv_cb, true); + } + if (empty_sector > 0 && empty_kv == FAILED_ADDR) + { + if (empty_sector > FDB_GC_EMPTY_SEC_THRESHOLD || db->gc_request) + { + sector_iterator(db, sector, FDB_SECTOR_STORE_EMPTY, &arg, NULL, alloc_kv_cb, true); + } + else + { + /* no space for new KV now will GC and retry */ + FDB_DEBUG("Trigger a GC check after alloc KV failed.\n"); + db->gc_request = true; + } + } + + return empty_kv; +} + +static fdb_err_t del_kv(fdb_kvdb_t db, const char *key, fdb_kv_t old_kv, bool complete_del) +{ + fdb_err_t result = FDB_NO_ERR; + uint32_t dirty_status_addr; + struct fdb_kv kv = {.status = FDB_KV_UNUSED}; + +#if (KV_STATUS_TABLE_SIZE >= FDB_DIRTY_STATUS_TABLE_SIZE) + uint8_t status_table[KV_STATUS_TABLE_SIZE]; +#else + uint8_t status_table[DIRTY_STATUS_TABLE_SIZE]; +#endif + + /* need find KV */ + if (!old_kv) + { + /* find KV */ + if (find_kv(db, key, &kv)) + { + old_kv = &kv; + } + else + { + FDB_DEBUG("Not found '%s' in KV.\n", key); + return FDB_KV_NAME_ERR; + } + } + /* change and save the new status */ + if (!complete_del) + { + result = _fdb_write_status((fdb_db_t)db, old_kv->addr.start, status_table, FDB_KV_STATUS_NUM, FDB_KV_PRE_DELETE, false); + db->last_is_complete_del = true; + } + else + { + result = _fdb_write_status((fdb_db_t)db, old_kv->addr.start, status_table, FDB_KV_STATUS_NUM, FDB_KV_DELETED, true); + + if (!db->last_is_complete_del && result == FDB_NO_ERR) + { +#ifdef FDB_KV_USING_CACHE + /* delete the KV in flash and cache */ + if (key != NULL) + { + /* when using del_kv(db, key, NULL, true) or del_kv(db, key, kv, true) in fdb_del_kv(db, ) and set_kv(db, ) */ + update_kv_cache(db, key, strlen(key), FDB_DATA_UNUSED); + } + else if (old_kv != NULL) + { + /* when using del_kv(db, NULL, kv, true) in move_kv(db, ) */ + update_kv_cache(db, old_kv->name, old_kv->name_len, FDB_DATA_UNUSED); + } +#endif /* FDB_KV_USING_CACHE */ + } + + db->last_is_complete_del = false; + } + + dirty_status_addr = FDB_ALIGN_DOWN(old_kv->addr.start, db_sec_size(db)) + SECTOR_DIRTY_OFFSET; + /* read and change the sector dirty status */ + if (result == FDB_NO_ERR && _fdb_read_status((fdb_db_t)db, dirty_status_addr, status_table, FDB_SECTOR_DIRTY_STATUS_NUM) == FDB_SECTOR_DIRTY_FALSE) + { + result = _fdb_write_status((fdb_db_t)db, dirty_status_addr, status_table, FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_TRUE, true); +#ifdef FDB_KV_USING_CACHE + { + kv_sec_info_t sector_cache = get_sector_from_cache(db, FDB_ALIGN_DOWN(old_kv->addr.start, db_sec_size(db))); + if (sector_cache) + { + sector_cache->status.dirty = FDB_SECTOR_DIRTY_TRUE; + } + } +#endif /* FDB_KV_USING_CACHE */ + } + + return result; +} + +/* + * move the KV to new space + */ +static fdb_err_t move_kv(fdb_kvdb_t db, fdb_kv_t kv) +{ + fdb_err_t result = FDB_NO_ERR; + uint8_t status_table[KV_STATUS_TABLE_SIZE]; + uint32_t kv_addr; + struct kvdb_sec_info sector; + + /* prepare to delete the current KV */ + if (kv->status == FDB_KV_WRITE) + { + del_kv(db, NULL, kv, false); + } + + if ((kv_addr = alloc_kv(db, §or, kv->len)) != FAILED_ADDR) + { + if (db->in_recovery_check && kv->status == FDB_KV_PRE_DELETE) + { + struct fdb_kv kv_bak; + char name[FDB_KV_NAME_MAX + 1] = {0}; + strncpy(name, kv->name, kv->name_len); + /* check the KV in flash is already create success */ + if (find_kv_no_cache(db, name, &kv_bak)) + { + /* already create success, don't need to duplicate */ + result = FDB_NO_ERR; + goto __exit; + } + } + } + else + { + return FDB_SAVED_FULL; + } + /* start move the KV */ + { + uint8_t buf[32]; + size_t len, size, kv_len = kv->len; + + /* update the new KV sector status first */ + update_sec_status(db, §or, kv->len, NULL); + + _fdb_write_status((fdb_db_t)db, kv_addr, status_table, FDB_KV_STATUS_NUM, FDB_KV_PRE_WRITE, false); + kv_len -= KV_MAGIC_OFFSET; + for (len = 0, size = 0; len < kv_len; len += size) + { + if (len + sizeof(buf) < kv_len) + { + size = sizeof(buf); + } + else + { + size = kv_len - len; + } + _fdb_flash_read((fdb_db_t)db, kv->addr.start + KV_MAGIC_OFFSET + len, (uint32_t *)buf, FDB_WG_ALIGN(size)); + result = _fdb_flash_write((fdb_db_t)db, kv_addr + KV_MAGIC_OFFSET + len, (uint32_t *)buf, size, true); + } + _fdb_write_status((fdb_db_t)db, kv_addr, status_table, FDB_KV_STATUS_NUM, FDB_KV_WRITE, true); + +#ifdef FDB_KV_USING_CACHE + update_sector_empty_addr_cache(db, FDB_ALIGN_DOWN(kv_addr, db_sec_size(db)), + kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv->name_len) + FDB_WG_ALIGN(kv->value_len)); + update_kv_cache(db, kv->name, kv->name_len, kv_addr); +#endif /* FDB_KV_USING_CACHE */ + } + + FDB_DEBUG("Moved the KV (%.*s) from 0x%08" PRIX32 " to 0x%08" PRIX32 ".\n", kv->name_len, kv->name, kv->addr.start, kv_addr); + +__exit: + del_kv(db, NULL, kv, true); + + return result; +} + +static uint32_t new_kv(fdb_kvdb_t db, kv_sec_info_t sector, size_t kv_size) +{ + bool already_gc = false; + uint32_t empty_kv = FAILED_ADDR; + +__retry: + + if ((empty_kv = alloc_kv(db, sector, kv_size)) == FAILED_ADDR) + { + if (db->gc_request && !already_gc) + { + FDB_INFO("Warning: Alloc an KV (size %" PRIu32 ") failed when new KV. Now will GC then retry.\n", (uint32_t)kv_size); + gc_collect_by_free_size(db, kv_size); + already_gc = true; + goto __retry; + } + else if (already_gc) + { + FDB_INFO("Error: Alloc an KV (size %" PRIuLEAST16 ") failed after GC. KV full.\n", kv_size); + db->gc_request = false; + } + } + + return empty_kv; +} + +static uint32_t new_kv_ex(fdb_kvdb_t db, kv_sec_info_t sector, size_t key_len, size_t buf_len) +{ + size_t kv_len = KV_HDR_DATA_SIZE + FDB_WG_ALIGN(key_len) + FDB_WG_ALIGN(buf_len); + + return new_kv(db, sector, kv_len); +} + +static bool gc_check_cb(kv_sec_info_t sector, void *arg1, void *arg2) +{ + size_t *empty_sec = arg1; + + if (sector->check_ok) + { + *empty_sec = *empty_sec + 1; + } + + return false; +} + +static bool do_gc(kv_sec_info_t sector, void *arg1, void *arg2) +{ + struct fdb_kv kv; + struct gc_cb_args *gc = (struct gc_cb_args *)arg1; + fdb_kvdb_t db = gc->db; + + if (sector->check_ok && (sector->status.dirty == FDB_SECTOR_DIRTY_TRUE || sector->status.dirty == FDB_SECTOR_DIRTY_GC)) + { + uint8_t status_table[FDB_DIRTY_STATUS_TABLE_SIZE]; + /* change the sector status to GC */ + _fdb_write_status((fdb_db_t)db, sector->addr + SECTOR_DIRTY_OFFSET, status_table, FDB_SECTOR_DIRTY_STATUS_NUM, FDB_SECTOR_DIRTY_GC, true); + /* search all KV */ + kv.addr.start = sector->addr + SECTOR_HDR_DATA_SIZE; + do + { + read_kv(db, &kv); + if (kv.crc_is_ok && (kv.status == FDB_KV_WRITE || kv.status == FDB_KV_PRE_DELETE)) + { + /* move the KV to new space */ + if (move_kv(db, &kv) != FDB_NO_ERR) + { + FDB_INFO("Error: Moved the KV (%.*s) for GC failed.\n", kv.name_len, kv.name); + } + } + } while ((kv.addr.start = get_next_kv_addr(db, sector, &kv)) != FAILED_ADDR); + format_sector(db, sector->addr, SECTOR_NOT_COMBINED); + gc->cur_free_size += db_sec_size(db) - SECTOR_HDR_DATA_SIZE; + FDB_DEBUG("Collect a sector @0x%08" PRIX32 "\n", sector->addr); + /* update oldest_addr for next GC sector format */ + db_oldest_addr(db) = get_next_sector_addr(db, sector, 0); + if (gc->cur_free_size >= gc->setting_free_size) + return true; + } + + return false; +} + +static void gc_collect_by_free_size(fdb_kvdb_t db, size_t free_size) +{ + struct kvdb_sec_info sector; + size_t empty_sec = 0; + struct gc_cb_args arg = {db, 0, free_size, 0}; + + /* GC check the empty sector number */ + sector_iterator(db, §or, FDB_SECTOR_STORE_EMPTY, &empty_sec, NULL, gc_check_cb, false); + + /* do GC collect */ + FDB_DEBUG("The remain empty sector is %" PRIu32 ", GC threshold is %" PRIdLEAST16 ".\n", (uint32_t)empty_sec, FDB_GC_EMPTY_SEC_THRESHOLD); + if (empty_sec <= FDB_GC_EMPTY_SEC_THRESHOLD) + { + sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, &arg, NULL, do_gc, false); + } + + db->gc_request = false; +} + +/* + * The GC will be triggered on the following scene: + * 1. alloc an KV when the flash not has enough space + * 2. write an KV then the flash not has enough space + */ +static void gc_collect(fdb_kvdb_t db) +{ + gc_collect_by_free_size(db, db_max_size(db)); +} + +static fdb_err_t align_write(fdb_kvdb_t db, uint32_t addr, const uint32_t *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + size_t align_remain; + +#if (FDB_WRITE_GRAN / 8 > 0) + uint8_t align_data[FDB_WRITE_GRAN / 8]; + size_t align_data_size = sizeof(align_data); +#else + /* For compatibility with C89 */ + uint8_t align_data_u8, *align_data = &align_data_u8; + size_t align_data_size = 1; +#endif + + memset(align_data, FDB_BYTE_ERASED, align_data_size); + result = _fdb_flash_write((fdb_db_t)db, addr, buf, FDB_WG_ALIGN_DOWN(size), false); + + align_remain = size - FDB_WG_ALIGN_DOWN(size); + if (result == FDB_NO_ERR && align_remain) + { + memcpy(align_data, (uint8_t *)buf + FDB_WG_ALIGN_DOWN(size), align_remain); + result = _fdb_flash_write((fdb_db_t)db, addr + FDB_WG_ALIGN_DOWN(size), (uint32_t *)align_data, + align_data_size, false); + } + + return result; +} + +static fdb_err_t create_kv_blob(fdb_kvdb_t db, kv_sec_info_t sector, const char *key, const void *value, size_t len) +{ + fdb_err_t result = FDB_NO_ERR; + struct kv_hdr_data kv_hdr; + bool is_full = false; + uint32_t kv_addr = sector->empty_kv; + + if (strlen(key) > FDB_KV_NAME_MAX) + { + FDB_INFO("Error: The KV name length is more than %d\n", FDB_KV_NAME_MAX); + return FDB_KV_NAME_ERR; + } + + memset(&kv_hdr, FDB_BYTE_ERASED, sizeof(struct kv_hdr_data)); + kv_hdr.magic = KV_MAGIC_WORD; + kv_hdr.name_len = strlen(key); + kv_hdr.value_len = len; + kv_hdr.len = KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len) + FDB_WG_ALIGN(kv_hdr.value_len); + + if (kv_hdr.len > db_sec_size(db) - SECTOR_HDR_DATA_SIZE) + { + FDB_INFO("Error: The KV size is too big\n"); + return FDB_SAVED_FULL; + } + + if (kv_addr != FAILED_ADDR || (kv_addr = new_kv(db, sector, kv_hdr.len)) != FAILED_ADDR) + { + size_t align_remain; + /* update the sector status */ + if (result == FDB_NO_ERR) + { + result = update_sec_status(db, sector, kv_hdr.len, &is_full); + } + if (result == FDB_NO_ERR) + { + uint8_t ff = FDB_BYTE_ERASED; + /* start calculate CRC32 */ + kv_hdr.crc32 = 0; + /* CRC32(header.name_len + header.value_len + name + value), using sizeof(uint32_t) for compatible V1.x */ + kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &kv_hdr.name_len, sizeof(uint32_t)); + kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &kv_hdr.value_len, sizeof(uint32_t)); + kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, key, kv_hdr.name_len); + align_remain = FDB_WG_ALIGN(kv_hdr.name_len) - kv_hdr.name_len; + while (align_remain--) + { + kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &ff, 1); + } + kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, value, kv_hdr.value_len); + align_remain = FDB_WG_ALIGN(kv_hdr.value_len) - kv_hdr.value_len; + while (align_remain--) + { + kv_hdr.crc32 = fdb_calc_crc32(kv_hdr.crc32, &ff, 1); + } + /* write KV header data */ + result = write_kv_hdr(db, kv_addr, &kv_hdr); + } + /* write key name */ + if (result == FDB_NO_ERR) + { + result = align_write(db, kv_addr + KV_HDR_DATA_SIZE, (uint32_t *)key, kv_hdr.name_len); + +#ifdef FDB_KV_USING_CACHE + if (!is_full) + { + update_sector_empty_addr_cache(db, sector->addr, + kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len) + FDB_WG_ALIGN(kv_hdr.value_len)); + } + update_kv_cache(db, key, kv_hdr.name_len, kv_addr); +#endif /* FDB_KV_USING_CACHE */ + } + /* write value */ + if (result == FDB_NO_ERR) + { + result = align_write(db, kv_addr + KV_HDR_DATA_SIZE + FDB_WG_ALIGN(kv_hdr.name_len), value, + kv_hdr.value_len); + } + /* change the KV status to KV_WRITE */ + if (result == FDB_NO_ERR) + { + result = _fdb_write_status((fdb_db_t)db, kv_addr, kv_hdr.status_table, FDB_KV_STATUS_NUM, FDB_KV_WRITE, + true); + } + /* trigger GC collect when current sector is full */ + if (result == FDB_NO_ERR && is_full) + { + FDB_DEBUG("Trigger a GC check after created KV.\n"); + db->gc_request = true; + } + } + else + { + result = FDB_SAVED_FULL; + } + + return result; +} + +/** + * Delete an KV. + * + * @param db database object + * @param key KV name + * + * @return result + */ +fdb_err_t fdb_kv_del(fdb_kvdb_t db, const char *key) +{ + fdb_err_t result = FDB_NO_ERR; + + if (!db_init_ok(db)) + { + FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db)); + return FDB_INIT_FAILED; + } + + /* lock the KV cache */ + db_lock(db); + + result = del_kv(db, key, NULL, true); + + /* unlock the KV cache */ + db_unlock(db); + + return result; +} + +static fdb_err_t set_kv(fdb_kvdb_t db, const char *key, const void *value_buf, size_t buf_len) +{ + fdb_err_t result = FDB_NO_ERR; + bool kv_is_found = false; + + if (value_buf == NULL) + { + result = del_kv(db, key, NULL, true); + } + else + { + /* make sure the flash has enough space */ + if (new_kv_ex(db, &db->cur_sector, strlen(key), buf_len) == FAILED_ADDR) + { + return FDB_SAVED_FULL; + } + kv_is_found = find_kv(db, key, &db->cur_kv); + /* prepare to delete the old KV */ + if (kv_is_found) + { + result = del_kv(db, key, &db->cur_kv, false); + } + /* create the new KV */ + if (result == FDB_NO_ERR) + { + result = create_kv_blob(db, &db->cur_sector, key, value_buf, buf_len); + } + /* delete the old KV */ + if (kv_is_found && result == FDB_NO_ERR) + { + result = del_kv(db, key, &db->cur_kv, true); + } + /* process the GC after set KV */ + if (db->gc_request) + { + gc_collect_by_free_size(db, KV_HDR_DATA_SIZE + FDB_WG_ALIGN(strlen(key)) + FDB_WG_ALIGN(buf_len)); + } + } + + return result; +} + +/** + * Set a blob KV. If it blob value is NULL, delete it. + * If not find it in flash, then create it. + * + * @param db database object + * @param key KV name + * @param blob blob object + * + * @return result + */ +fdb_err_t fdb_kv_set_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob) +{ + fdb_err_t result = FDB_NO_ERR; + + if (!db_init_ok(db)) + { + FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db)); + return FDB_INIT_FAILED; + } + + /* lock the KV cache */ + db_lock(db); + + result = set_kv(db, key, blob->buf, blob->size); + + /* unlock the KV cache */ + db_unlock(db); + + return result; +} + +/** + * Set a string KV. If it value is NULL, delete it. + * If not find it in flash, then create it. + * + * @param db database object + * @param key KV name + * @param value KV value + * + * @return result + */ +fdb_err_t fdb_kv_set(fdb_kvdb_t db, const char *key, const char *value) +{ + struct fdb_blob blob; + + return fdb_kv_set_blob(db, key, fdb_blob_make(&blob, value, strlen(value))); +} + +/** + * recovery all KV to default. + * + * @param db database object + * @return result + */ +fdb_err_t fdb_kv_set_default(fdb_kvdb_t db) +{ + fdb_err_t result = FDB_NO_ERR; + uint32_t addr, i, value_len; + struct kvdb_sec_info sector; + + /* lock the KV cache */ + db_lock(db); + /* format all sectors */ + for (addr = 0; addr < db_max_size(db); addr += db_sec_size(db)) + { + result = format_sector(db, addr, SECTOR_NOT_COMBINED); + if (result != FDB_NO_ERR) + { + goto __exit; + } + } + /* create default KV */ + for (i = 0; i < db->default_kvs.num; i++) + { + /* It seems to be a string when value length is 0. + * This mechanism is for compatibility with older versions (less then V4.0). */ + if (db->default_kvs.kvs[i].value_len == 0) + { + value_len = strlen(db->default_kvs.kvs[i].value); + } + else + { + value_len = db->default_kvs.kvs[i].value_len; + } + sector.empty_kv = FAILED_ADDR; + create_kv_blob(db, §or, db->default_kvs.kvs[i].key, db->default_kvs.kvs[i].value, value_len); + if (result != FDB_NO_ERR) + { + goto __exit; + } + } + +__exit: + db_oldest_addr(db) = 0; + /* unlock the KV cache */ + db_unlock(db); + + return result; +} + +static bool print_kv_cb(fdb_kv_t kv, void *arg1, void *arg2) +{ + bool value_is_str = true, print_value = false; + size_t *using_size = arg1; + fdb_kvdb_t db = arg2; + + if (kv->crc_is_ok) + { + /* calculate the total using flash size */ + *using_size += kv->len; + /* check KV */ + if (kv->status == FDB_KV_WRITE) + { + FDB_PRINT("%.*s=", kv->name_len, kv->name); + + if (kv->value_len < FDB_STR_KV_VALUE_MAX_SIZE) + { + uint8_t buf[32]; + size_t len, size; + __reload: + /* check the value is string */ + for (len = 0, size = 0; len < kv->value_len; len += size) + { + if (len + sizeof(buf) < kv->value_len) + { + size = sizeof(buf); + } + else + { + size = kv->value_len - len; + } + _fdb_flash_read((fdb_db_t)db, kv->addr.value + len, (uint32_t *)buf, FDB_WG_ALIGN(size)); + if (print_value) + { + FDB_PRINT("%.*s", (int)size, buf); + } + else if (!fdb_is_str(buf, size)) + { + value_is_str = false; + break; + } + } + } + else + { + value_is_str = false; + } + if (value_is_str && !print_value) + { + print_value = true; + goto __reload; + } + else if (!value_is_str) + { + FDB_PRINT("blob @0x%08" PRIX32 " %" PRIu32 "bytes", kv->addr.value, kv->value_len); + } + FDB_PRINT("\n"); + } + } + + return false; +} + +/** + * Print all KV. + * + * @param db database object + */ +void fdb_kv_print(fdb_kvdb_t db) +{ + struct fdb_kv kv; + size_t using_size = 0; + + if (!db_init_ok(db)) + { + FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db)); + return; + } + + /* lock the KV cache */ + db_lock(db); + + kv_iterator(db, &kv, &using_size, db, print_kv_cb); + + FDB_PRINT("\nmode: next generation\n"); + FDB_PRINT("size: %" PRIu32 "/%" PRIu32 " bytes.\n", (uint32_t)using_size + ((SECTOR_NUM - FDB_GC_EMPTY_SEC_THRESHOLD) * SECTOR_HDR_DATA_SIZE), + db_max_size(db) - db_sec_size(db) * FDB_GC_EMPTY_SEC_THRESHOLD); + + /* unlock the KV cache */ + db_unlock(db); +} + +#ifdef FDB_KV_AUTO_UPDATE +/* + * Auto update KV to latest default when current setting version number is changed. + */ +static void kv_auto_update(fdb_kvdb_t db) +{ + size_t saved_ver_num, setting_ver_num = db->ver_num; + + if (get_kv(db, VER_NUM_KV_NAME, &saved_ver_num, sizeof(size_t), NULL) > 0) + { + /* check version number */ + if (saved_ver_num != setting_ver_num) + { + size_t i, value_len; + FDB_DEBUG("Update the KV from version %zu to %zu.\n", saved_ver_num, setting_ver_num); + for (i = 0; i < db->default_kvs.num; i++) + { + /* add a new KV when it's not found */ + if (!find_kv(db, db->default_kvs.kvs[i].key, &db->cur_kv)) + { + /* It seems to be a string when value length is 0. + * This mechanism is for compatibility with older versions (less then V4.0). */ + if (db->default_kvs.kvs[i].value_len == 0) + { + value_len = strlen(db->default_kvs.kvs[i].value); + } + else + { + value_len = db->default_kvs.kvs[i].value_len; + } + db->cur_sector.empty_kv = FAILED_ADDR; + create_kv_blob(db, &db->cur_sector, db->default_kvs.kvs[i].key, db->default_kvs.kvs[i].value, value_len); + } + } + } + else + { + /* version number not changed now return */ + return; + } + } + + set_kv(db, VER_NUM_KV_NAME, &setting_ver_num, sizeof(size_t)); +} +#endif /* FDB_KV_AUTO_UPDATE */ + +static bool check_oldest_addr_cb(kv_sec_info_t sector, void *arg1, void *arg2) +{ + uint32_t *sector_oldest_addr = (uint32_t *)arg1; + fdb_sector_store_status_t *last_sector_status = (fdb_sector_store_status_t *)arg2; + + /* The oldest address is 0 by default. + * The new oldest sector is found when sector status change from empty to full or using. + */ + if (*last_sector_status == FDB_SECTOR_STORE_EMPTY && (sector->status.store == FDB_SECTOR_STORE_FULL || sector->status.store == FDB_SECTOR_STORE_USING)) + { + *sector_oldest_addr = sector->addr; + } + + *last_sector_status = sector->status.store; + return false; +} + +static bool check_sec_hdr_cb(kv_sec_info_t sector, void *arg1, void *arg2) +{ + if (!sector->check_ok) + { + size_t *failed_count = arg1; + fdb_kvdb_t db = arg2; + + (*failed_count)++; + if (db->parent.not_formatable) + { + return true; + } + else + { + FDB_INFO("Sector header info is incorrect. Auto format this sector (0x%08" PRIX32 ").\n", sector->addr); + format_sector(db, sector->addr, SECTOR_NOT_COMBINED); + } + } + + return false; +} + +static bool check_and_recovery_gc_cb(kv_sec_info_t sector, void *arg1, void *arg2) +{ + fdb_kvdb_t db = arg1; + + if (sector->check_ok && sector->status.dirty == FDB_SECTOR_DIRTY_GC) + { + /* make sure the GC request flag to true */ + db->gc_request = true; + /* resume the GC operate */ + gc_collect(db); + } + + return false; +} + +static bool check_and_recovery_kv_cb(fdb_kv_t kv, void *arg1, void *arg2) +{ + fdb_kvdb_t db = arg1; + + /* recovery the prepare deleted KV */ + if (kv->crc_is_ok && kv->status == FDB_KV_PRE_DELETE) + { + FDB_INFO("Found an KV (%.*s) which has changed value failed. Now will recovery it.\n", kv->name_len, kv->name); + /* recovery the old KV */ + if (move_kv(db, kv) == FDB_NO_ERR) + { + FDB_DEBUG("Recovery the KV successful.\n"); + } + else + { + FDB_DEBUG("Warning: Moved an KV (size %" PRIu32 ") failed when recovery. Now will GC then retry.\n", kv->len); + return true; + } + } + else if (kv->status == FDB_KV_PRE_WRITE) + { + uint8_t status_table[KV_STATUS_TABLE_SIZE]; + /* the KV has not write finish, change the status to error */ + // TODO Draw the state replacement diagram of exception handling + _fdb_write_status((fdb_db_t)db, kv->addr.start, status_table, FDB_KV_STATUS_NUM, FDB_KV_ERR_HDR, true); + return true; + } + else if (kv->crc_is_ok && kv->status == FDB_KV_WRITE) + { +#ifdef FDB_KV_USING_CACHE + /* update the cache when first load. If caching is disabled, this step is not performed */ + update_kv_cache(db, kv->name, kv->name_len, kv->addr.start); +#endif + } + + return false; +} + +/** + * Check and load the flash KV. + * + * @return result + */ +static fdb_err_t _fdb_kv_load(fdb_kvdb_t db) +{ + fdb_err_t result = FDB_NO_ERR; + struct fdb_kv kv; + struct kvdb_sec_info sector; + size_t check_failed_count = 0; + + db->in_recovery_check = true; + /* check all sector header */ + sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, &check_failed_count, db, check_sec_hdr_cb, false); + if (db->parent.not_formatable && check_failed_count > 0) + { + return FDB_READ_ERR; + } + /* all sector header check failed */ + if (check_failed_count == SECTOR_NUM) + { + FDB_INFO("All sector header is incorrect. Set it to default.\n"); + fdb_kv_set_default(db); + } + + /* check all sector header for recovery GC */ + sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, db, NULL, check_and_recovery_gc_cb, false); + +__retry: + /* check all KV for recovery */ + kv_iterator(db, &kv, db, NULL, check_and_recovery_kv_cb); + if (db->gc_request) + { + gc_collect(db); + goto __retry; + } + + db->in_recovery_check = false; + + return result; +} + +/** + * This function will get or set some options of the database + * + * @param db database object + * @param cmd the control command + * @param arg the argument + */ +void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg) +{ + FDB_ASSERT(db); + + switch (cmd) + { + case FDB_KVDB_CTRL_SET_SEC_SIZE: + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.sec_size = *(uint32_t *)arg; + break; + case FDB_KVDB_CTRL_GET_SEC_SIZE: + *(uint32_t *)arg = db->parent.sec_size; + break; + case FDB_KVDB_CTRL_SET_LOCK: +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + db->parent.lock = (void (*)(fdb_db_t db))arg; +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + break; + case FDB_KVDB_CTRL_SET_UNLOCK: +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + db->parent.unlock = (void (*)(fdb_db_t db))arg; +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + break; + case FDB_KVDB_CTRL_SET_FILE_MODE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.file_mode = *(bool *)arg; +#else + FDB_INFO("Error: set file mode Failed. Please defined the FDB_USING_FILE_MODE macro."); +#endif + break; + case FDB_KVDB_CTRL_SET_MAX_SIZE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.max_size = *(uint32_t *)arg; +#endif + break; + case FDB_KVDB_CTRL_SET_NOT_FORMAT: + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.not_formatable = *(bool *)arg; + break; + } +} + +/** + * The KV database initialization. + * + * @param db database object + * @param name database name + * @param path FAL mode: partition name, file mode: database saved directory path + * @param default_kv the default KV set @see fdb_default_kv + * @param user_data user data + * + * @return result + */ +fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv, + void *user_data) +{ + fdb_err_t result = FDB_NO_ERR; + struct kvdb_sec_info sector; + +#ifdef FDB_KV_USING_CACHE + size_t i; +#endif + + /* must be aligned with write granularity */ + FDB_ASSERT((FDB_STR_KV_VALUE_MAX_SIZE * 8) % FDB_WRITE_GRAN == 0); + + result = _fdb_init_ex((fdb_db_t)db, name, path, FDB_DB_TYPE_KV, user_data); + if (result != FDB_NO_ERR) + { + goto __exit; + } + + /* lock the KVDB */ + db_lock(db); + + db->gc_request = false; + db->in_recovery_check = false; + if (default_kv) + { + db->default_kvs = *default_kv; + } + else + { + db->default_kvs.num = 0; + db->default_kvs.kvs = NULL; + } + + { /* find the oldest sector address */ + uint32_t sector_oldest_addr = 0; + fdb_sector_store_status_t last_sector_status = FDB_SECTOR_STORE_UNUSED; + + db_oldest_addr(db) = 0; + sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, §or_oldest_addr, &last_sector_status, + check_oldest_addr_cb, false); + db_oldest_addr(db) = sector_oldest_addr; + FDB_DEBUG("The oldest addr is @0x%08" PRIX32 "\n", db_oldest_addr(db)); + } + /* there is at least one empty sector for GC. */ + FDB_ASSERT((FDB_GC_EMPTY_SEC_THRESHOLD > 0 && FDB_GC_EMPTY_SEC_THRESHOLD < SECTOR_NUM)) + +#ifdef FDB_KV_USING_CACHE + for (i = 0; i < FDB_SECTOR_CACHE_TABLE_SIZE; i++) + { + db->sector_cache_table[i].check_ok = false; + db->sector_cache_table[i].empty_kv = FAILED_ADDR; + db->sector_cache_table[i].addr = FDB_DATA_UNUSED; + } + for (i = 0; i < FDB_KV_CACHE_TABLE_SIZE; i++) + { + db->kv_cache_table[i].addr = FDB_DATA_UNUSED; + } +#endif /* FDB_KV_USING_CACHE */ + + FDB_DEBUG("KVDB size is %" PRIu32 " bytes.\n", db_max_size(db)); + + result = _fdb_kv_load(db); + +#ifdef FDB_KV_AUTO_UPDATE + if (result == FDB_NO_ERR) + { + kv_auto_update(db); + } +#endif + + /* unlock the KVDB */ + db_unlock(db); + +__exit: + + _fdb_init_finish((fdb_db_t)db, result); + + return result; +} + +/** + * The KV database initialization. + * + * @param db database object + * + * @return result + */ +fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db) +{ + _fdb_deinit((fdb_db_t)db); + + return FDB_NO_ERR; +} + +/** + * The KV database initialization. + * + * @param db database object + * @param itr iterator structure to be initialized + * + * @return pointer to the iterator initialized. + */ +fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr) +{ + itr->curr_kv.addr.start = 0; + + /* If iterator statistics is needed */ + itr->iterated_cnt = 0; + itr->iterated_obj_bytes = 0; + itr->iterated_value_bytes = 0; + itr->traversed_len = 0; + /* Start from sector head */ + itr->sector_addr = db_oldest_addr(db); + return itr; +} + +/** + * The KV database iterator. + * + * @param db database object + * @param itr the iterator structure + * + * @return false if iteration is ended, true if iteration is not ended. + */ +bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr) +{ + struct kvdb_sec_info sector; + fdb_kv_t kv = &(itr->curr_kv); + + do + { + if (read_sector_info(db, itr->sector_addr, §or, false) == FDB_NO_ERR) + { + if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) + { + if (kv->addr.start == 0) + { + kv->addr.start = sector.addr + SECTOR_HDR_DATA_SIZE; + } + else if ((kv->addr.start = get_next_kv_addr(db, §or, kv)) == FAILED_ADDR) + { + kv->addr.start = 0; + itr->traversed_len += db_sec_size(db); + continue; + } + do + { + read_kv(db, kv); + if (kv->status == FDB_KV_WRITE && kv->crc_is_ok == true) + { + /* We got a valid kv here. */ + /* If iterator statistics is needed */ + itr->iterated_cnt++; + itr->iterated_obj_bytes += kv->len; + itr->iterated_value_bytes += kv->value_len; + return true; + } + } while ((kv->addr.start = get_next_kv_addr(db, §or, kv)) != FAILED_ADDR); + } + } + /** Set kv->addr.start to 0 when we get into a new sector so that if we successfully get the next sector info, + * the kv->addr.start is set to the new sector.addr + SECTOR_HDR_DATA_SIZE. + */ + kv->addr.start = 0; + itr->traversed_len += db_sec_size(db); + } while ((itr->sector_addr = get_next_sector_addr(db, §or, itr->traversed_len)) != FAILED_ADDR); + /* Finally we have iterated all the KVs. */ + return false; +} + +/** + * The database inergrity check + * + * @param db database object + * + * @return result, FDB_NO_ERR: check OK + */ +fdb_err_t fdb_kvdb_check(fdb_kvdb_t db) +{ + fdb_err_t result = FDB_NO_ERR; + uint32_t sec_addr, traversed_len = 0; + struct kvdb_sec_info sector; + struct fdb_kv kv; + + if (!db_init_ok(db)) + { + FDB_INFO("Error: KV (%s) isn't initialize OK.\n", db_name(db)); + return FDB_INIT_FAILED; + } + + /* lock the KV cache */ + db_lock(db); + + sec_addr = db_oldest_addr(db); + /* search all sectors */ + do + { + traversed_len += db_sec_size(db); + result = read_sector_info(db, sec_addr, §or, false); + if (result == FDB_NO_ERR) + { + /* sector has KV */ + if (sector.status.store == FDB_SECTOR_STORE_USING || sector.status.store == FDB_SECTOR_STORE_FULL) + { + kv.addr.start = sector.addr + SECTOR_HDR_DATA_SIZE; + /* search all KV */ + do + { + result = read_kv(db, &kv); + } while ((kv.addr.start = get_next_kv_addr(db, §or, &kv)) != FAILED_ADDR && result == FDB_NO_ERR); + } + } + } while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR && result == FDB_NO_ERR); + + /* unlock the KV cache */ + db_unlock(db); + + return result; +} + +#endif /* defined(FDB_USING_KVDB) */ diff --git a/User/lib/flashdb/fdb_low_lvl.h b/User/lib/flashdb/fdb_low_lvl.h new file mode 100644 index 0000000..c252dca --- /dev/null +++ b/User/lib/flashdb/fdb_low_lvl.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief low level API and definition + */ + +#ifndef _FDB_LOW_LVL_H_ +#define _FDB_LOW_LVL_H_ + +#include +#include + +#if (FDB_WRITE_GRAN == 1) +#define FDB_STATUS_TABLE_SIZE(status_number) ((status_number * FDB_WRITE_GRAN + 7)/8) +#else +#define FDB_STATUS_TABLE_SIZE(status_number) (((status_number - 1) * FDB_WRITE_GRAN + 7)/8) +#endif + +/* the data is erased */ +#define FDB_BYTE_ERASED 0xFF +/* the data is written */ +#define FDB_BYTE_WRITTEN 0x00 + +/* Return the most contiguous size aligned at specified width. RT_ALIGN(13, 4) + * would return 16. + */ +#define FDB_ALIGN(size, align) (((size) + (align) - 1) - (((size) + (align) -1) % (align))) +/* align by write granularity */ +#define FDB_WG_ALIGN(size) (FDB_ALIGN(size, ((FDB_WRITE_GRAN + 7)/8))) +/** + * Return the down number of aligned at specified width. RT_ALIGN_DOWN(13, 4) + * would return 12. + */ +#define FDB_ALIGN_DOWN(size, align) (((size) / (align)) * (align)) +/* align down by write granularity */ +#define FDB_WG_ALIGN_DOWN(size) (FDB_ALIGN_DOWN(size, (FDB_WRITE_GRAN + 7)/8)) + +#define FDB_STORE_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_SECTOR_STORE_STATUS_NUM) +#define FDB_DIRTY_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_SECTOR_DIRTY_STATUS_NUM) + +/* the data is unused */ +#if (FDB_BYTE_ERASED == 0xFF) +#define FDB_DATA_UNUSED 0xFFFFFFFF +#else +#define FDB_DATA_UNUSED 0x00000000 +#endif + +/* invalid address */ +#define FDB_FAILED_ADDR 0xFFFFFFFF + +size_t _fdb_set_status(uint8_t status_table[], size_t status_num, size_t status_index); +size_t _fdb_get_status(uint8_t status_table[], size_t status_num); +uint32_t _fdb_continue_ff_addr(fdb_db_t db, uint32_t start, uint32_t end); +fdb_err_t _fdb_init_ex(fdb_db_t db, const char *name, const char *part_name, fdb_db_type type, void *user_data); +void _fdb_init_finish(fdb_db_t db, fdb_err_t result); +void _fdb_deinit(fdb_db_t db); +const char *_fdb_db_path(fdb_db_t db); +fdb_err_t _fdb_write_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t status_num, size_t status_index, bool sync); +size_t _fdb_read_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t total_num); +fdb_err_t _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size); +fdb_err_t _fdb_flash_erase(fdb_db_t db, uint32_t addr, size_t size); +fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync); + +#endif /* _FDB_LOW_LVL_H_ */ diff --git a/User/lib/flashdb/fdb_tsdb.c b/User/lib/flashdb/fdb_tsdb.c new file mode 100644 index 0000000..d019476 --- /dev/null +++ b/User/lib/flashdb/fdb_tsdb.c @@ -0,0 +1,1022 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief TSDB feature. + * + * Time series log (like TSDB) feature implement source file. + * + * TSL is time series log, the TSDB saved many TSLs. + */ + +#include +#include +#include +#include + +#define FDB_LOG_TAG "[tsl]" +/* rewrite log prefix */ +#undef FDB_LOG_PREFIX2 +#define FDB_LOG_PREFIX2() FDB_PRINT("[%s][%s] ", db_name(db), _fdb_db_path((fdb_db_t)db)) + +#if defined(FDB_USING_TSDB) + +#if (FDB_WRITE_GRAN == 64) || (FDB_WRITE_GRAN == 128) +#error "Flash 64 or 128 bits write granularity is not supported in TSDB yet!" +#endif + +/* magic word(`T`, `S`, `L`, `0`) */ +#define SECTOR_MAGIC_WORD 0x304C5354 + +#define TSL_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_TSL_STATUS_NUM) + +#define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data))) +#define LOG_IDX_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct log_idx_data))) +#define LOG_IDX_TS_OFFSET ((unsigned long)(&((struct log_idx_data *)0)->time)) +#define SECTOR_MAGIC_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->magic)) +#define SECTOR_START_TIME_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->start_time)) +#define SECTOR_END0_TIME_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->end_info[0].time)) +#define SECTOR_END0_IDX_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->end_info[0].index)) +#define SECTOR_END0_STATUS_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->end_info[0].status)) +#define SECTOR_END1_TIME_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->end_info[1].time)) +#define SECTOR_END1_IDX_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->end_info[1].index)) +#define SECTOR_END1_STATUS_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->end_info[1].status)) + +/* the next address is get failed */ +#define FAILED_ADDR 0xFFFFFFFF + +#define db_name(db) (((fdb_db_t)db)->name) +#define db_init_ok(db) (((fdb_db_t)db)->init_ok) +#define db_sec_size(db) (((fdb_db_t)db)->sec_size) +#define db_max_size(db) (((fdb_db_t)db)->max_size) +#define db_oldest_addr(db) (((fdb_db_t)db)->oldest_addr) + +#define db_lock(db) \ + do { \ + if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db); \ + } while(0); + +#define db_unlock(db) \ + do { \ + if (((fdb_db_t)db)->unlock) ((fdb_db_t)db)->unlock((fdb_db_t)db); \ + } while(0); + +#define _FDB_WRITE_STATUS(db, addr, status_table, status_num, status_index, sync) \ + do { \ + result = _fdb_write_status((fdb_db_t)db, addr, status_table, status_num, status_index, sync);\ + if (result != FDB_NO_ERR) return result; \ + } while(0); + +#define FLASH_WRITE(db, addr, buf, size, sync) \ + do { \ + result = _fdb_flash_write((fdb_db_t)db, addr, buf, size, sync); \ + if (result != FDB_NO_ERR) return result; \ + } while(0); + +struct sector_hdr_data { + uint8_t status[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see fdb_sector_store_status_t */ + uint32_t magic; /**< magic word(`T`, `S`, `L`, `0`) */ + fdb_time_t start_time; /**< the first start node's timestamp */ + struct { + fdb_time_t time; /**< the last end node's timestamp */ + uint32_t index; /**< the last end node's index */ + uint8_t status[TSL_STATUS_TABLE_SIZE]; /**< end node status, @see fdb_tsl_status_t */ + } end_info[2]; + uint32_t reserved; +}; +typedef struct sector_hdr_data *sector_hdr_data_t; + +/* time series log node index data */ +struct log_idx_data { + uint8_t status_table[TSL_STATUS_TABLE_SIZE]; /**< node status, @see fdb_tsl_status_t */ + fdb_time_t time; /**< node timestamp */ + uint32_t log_len; /**< node total length (header + name + value), must align by FDB_WRITE_GRAN */ + uint32_t log_addr; /**< node address */ +}; +typedef struct log_idx_data *log_idx_data_t; + +struct query_count_args { + fdb_tsl_status_t status; + size_t count; +}; + +struct check_sec_hdr_cb_args { + fdb_tsdb_t db; + bool check_failed; + size_t empty_num; + uint32_t empty_addr; +}; + +static fdb_err_t read_tsl(fdb_tsdb_t db, fdb_tsl_t tsl) +{ + struct log_idx_data idx; + /* read TSL index raw data */ + _fdb_flash_read((fdb_db_t)db, tsl->addr.index, (uint32_t *) &idx, sizeof(struct log_idx_data)); + tsl->status = (fdb_tsl_status_t) _fdb_get_status(idx.status_table, FDB_TSL_STATUS_NUM); + if ((tsl->status == FDB_TSL_PRE_WRITE) || (tsl->status == FDB_TSL_UNUSED)) { + tsl->log_len = db->max_len; + tsl->addr.log = FDB_DATA_UNUSED; + tsl->time = 0; + } else { + tsl->log_len = idx.log_len; + tsl->addr.log = idx.log_addr; + tsl->time = idx.time; + } + + return FDB_NO_ERR; +} + +static uint32_t get_next_sector_addr(fdb_tsdb_t db, tsdb_sec_info_t pre_sec, uint32_t traversed_len) +{ + if (traversed_len + db_sec_size(db) <= db_max_size(db)) { + if (pre_sec->addr + db_sec_size(db) < db_max_size(db)) { + return pre_sec->addr + db_sec_size(db); + } else { + /* the next sector is on the top of the database */ + return 0; + } + } else { + /* finished */ + return FAILED_ADDR; + } +} + +static uint32_t get_next_tsl_addr(tsdb_sec_info_t sector, fdb_tsl_t pre_tsl) +{ + uint32_t addr = FAILED_ADDR; + + if (sector->status == FDB_SECTOR_STORE_EMPTY) { + return FAILED_ADDR; + } + + if (pre_tsl->addr.index + LOG_IDX_DATA_SIZE <= sector->end_idx) { + addr = pre_tsl->addr.index + LOG_IDX_DATA_SIZE; + } else { + /* no TSL */ + return FAILED_ADDR; + } + + return addr; +} + +static uint32_t get_last_tsl_addr(tsdb_sec_info_t sector, fdb_tsl_t pre_tsl) +{ + uint32_t addr = FAILED_ADDR; + + if (sector->status == FDB_SECTOR_STORE_EMPTY) { + return FAILED_ADDR; + } + + if (pre_tsl->addr.index >= (sector->addr + SECTOR_HDR_DATA_SIZE + LOG_IDX_DATA_SIZE)) { + addr = pre_tsl->addr.index - LOG_IDX_DATA_SIZE; + } else { + return FAILED_ADDR; + } + + return addr; +} + +static uint32_t get_last_sector_addr(fdb_tsdb_t db, tsdb_sec_info_t pre_sec, uint32_t traversed_len) +{ + if (traversed_len + db_sec_size(db) <= db_max_size(db)) { + if (pre_sec->addr >= db_sec_size(db)) { + /* the next sector is previous sector */ + return pre_sec->addr - db_sec_size(db); + } else { + /* the next sector is the last sector */ + return db_max_size(db) - db_sec_size(db); + } + } else { + return FAILED_ADDR; + } +} + +static fdb_err_t read_sector_info(fdb_tsdb_t db, uint32_t addr, tsdb_sec_info_t sector, bool traversal) +{ + fdb_err_t result = FDB_NO_ERR; + struct sector_hdr_data sec_hdr; + + FDB_ASSERT(sector); + + /* read sector header raw data */ + _fdb_flash_read((fdb_db_t)db, addr, (uint32_t *)&sec_hdr, sizeof(struct sector_hdr_data)); + + sector->addr = addr; + sector->magic = sec_hdr.magic; + + /* check magic word */ + if (sector->magic != SECTOR_MAGIC_WORD) { + sector->check_ok = false; + return FDB_INIT_FAILED; + } + sector->check_ok = true; + sector->status = (fdb_sector_store_status_t) _fdb_get_status(sec_hdr.status, FDB_SECTOR_STORE_STATUS_NUM); + sector->start_time = sec_hdr.start_time; + sector->end_info_stat[0] = (fdb_tsl_status_t) _fdb_get_status(sec_hdr.end_info[0].status, FDB_TSL_STATUS_NUM); + sector->end_info_stat[1] = (fdb_tsl_status_t) _fdb_get_status(sec_hdr.end_info[1].status, FDB_TSL_STATUS_NUM); + if (sector->end_info_stat[0] == FDB_TSL_WRITE) { + sector->end_time = sec_hdr.end_info[0].time; + sector->end_idx = sec_hdr.end_info[0].index; + } else if (sector->end_info_stat[1] == FDB_TSL_WRITE) { + sector->end_time = sec_hdr.end_info[1].time; + sector->end_idx = sec_hdr.end_info[1].index; + } else if (sector->end_info_stat[0] == FDB_TSL_PRE_WRITE && sector->end_info_stat[1] == FDB_TSL_PRE_WRITE) { + //TODO There is no valid end node info on this sector, need impl fast query this sector by fdb_tsl_iter_by_time + FDB_ASSERT(0); + } + /* traversal all TSL and calculate the remain space size */ + sector->empty_idx = sector->addr + SECTOR_HDR_DATA_SIZE; + sector->empty_data = sector->addr + db_sec_size(db); + /* the TSL's data is saved from sector bottom, and the TSL's index saved from the sector top */ + sector->remain = sector->empty_data - sector->empty_idx; + if (sector->status == FDB_SECTOR_STORE_USING && traversal) { + struct fdb_tsl tsl; + + tsl.addr.index = sector->empty_idx; + while (read_tsl(db, &tsl) == FDB_NO_ERR) { + if (tsl.status == FDB_TSL_UNUSED) { + break; + } + sector->end_time = tsl.time; + sector->end_idx = tsl.addr.index; + sector->empty_idx += LOG_IDX_DATA_SIZE; + sector->empty_data -= FDB_WG_ALIGN(tsl.log_len); + tsl.addr.index += LOG_IDX_DATA_SIZE; + if (sector->remain > LOG_IDX_DATA_SIZE + FDB_WG_ALIGN(tsl.log_len)) { + sector->remain -= (LOG_IDX_DATA_SIZE + FDB_WG_ALIGN(tsl.log_len)); + } else { + FDB_INFO("Error: this TSL (0x%08" PRIX32 ") size (%" PRIu32 ") is out of bound.\n", tsl.addr.index, tsl.log_len); + sector->remain = 0; + result = FDB_READ_ERR; + break; + } + } + } + + return result; +} + +static fdb_err_t format_sector(fdb_tsdb_t db, uint32_t addr) +{ + fdb_err_t result = FDB_NO_ERR; + struct sector_hdr_data sec_hdr; + + FDB_ASSERT(addr % db_sec_size(db) == 0); + + result = _fdb_flash_erase((fdb_db_t)db, addr, db_sec_size(db)); + if (result == FDB_NO_ERR) { + _FDB_WRITE_STATUS(db, addr, sec_hdr.status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_EMPTY, true); + /* set the magic */ + sec_hdr.magic = SECTOR_MAGIC_WORD; + FLASH_WRITE(db, addr + SECTOR_MAGIC_OFFSET, &sec_hdr.magic, sizeof(sec_hdr.magic), true); + } + + return result; +} + +static void sector_iterator(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_sector_store_status_t status, void *arg1, + void *arg2, bool (*callback)(tsdb_sec_info_t sector, void *arg1, void *arg2), bool traversal) +{ + uint32_t sec_addr = sector->addr, traversed_len = 0; + + /* search all sectors */ + do { + read_sector_info(db, sec_addr, sector, false); + if (status == FDB_SECTOR_STORE_UNUSED || status == sector->status) { + if (traversal) { + read_sector_info(db, sec_addr, sector, true); + } + /* iterator is interrupted when callback return true */ + if (callback && callback(sector, arg1, arg2)) { + return; + } + } + traversed_len += db_sec_size(db); + } while ((sec_addr = get_next_sector_addr(db, sector, traversed_len)) != FAILED_ADDR); +} + +static fdb_err_t write_tsl(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t time) +{ + fdb_err_t result = FDB_NO_ERR; + struct log_idx_data idx; + uint32_t idx_addr = db->cur_sec.empty_idx; + + idx.log_len = blob->size; + idx.time = time; + idx.log_addr = db->cur_sec.empty_data - FDB_WG_ALIGN(idx.log_len); + /* write the status will by write granularity */ + _FDB_WRITE_STATUS(db, idx_addr, idx.status_table, FDB_TSL_STATUS_NUM, FDB_TSL_PRE_WRITE, false); + /* write other index info */ + FLASH_WRITE(db, idx_addr + LOG_IDX_TS_OFFSET, &idx.time, sizeof(struct log_idx_data) - LOG_IDX_TS_OFFSET, false); + /* write blob data */ + FLASH_WRITE(db, idx.log_addr, blob->buf, blob->size, false); + /* write the status will by write granularity */ + _FDB_WRITE_STATUS(db, idx_addr, idx.status_table, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE, true); + + return result; +} + +static fdb_err_t update_sec_status(fdb_tsdb_t db, tsdb_sec_info_t sector, fdb_blob_t blob, fdb_time_t cur_time) +{ + fdb_err_t result = FDB_NO_ERR; + uint8_t status[FDB_STORE_STATUS_TABLE_SIZE]; + + if (sector->status == FDB_SECTOR_STORE_USING && sector->remain < LOG_IDX_DATA_SIZE + FDB_WG_ALIGN(blob->size)) { + uint8_t end_status[TSL_STATUS_TABLE_SIZE]; + uint32_t end_index = sector->empty_idx - LOG_IDX_DATA_SIZE, new_sec_addr, cur_sec_addr = sector->addr; + /* save the end node index and timestamp */ + if (sector->end_info_stat[0] == FDB_TSL_UNUSED) { + _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END0_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_PRE_WRITE, false); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t), false); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END0_IDX_OFFSET, &end_index, sizeof(end_index), false); + _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END0_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE, true); + } else if (sector->end_info_stat[1] == FDB_TSL_UNUSED) { + _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END1_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_PRE_WRITE, false); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_TIME_OFFSET, (uint32_t * )&db->last_time, sizeof(fdb_time_t), false); + FLASH_WRITE(db, cur_sec_addr + SECTOR_END1_IDX_OFFSET, &end_index, sizeof(end_index), false); + _FDB_WRITE_STATUS(db, cur_sec_addr + SECTOR_END1_STATUS_OFFSET, end_status, FDB_TSL_STATUS_NUM, FDB_TSL_WRITE, true); + } + /* change current sector to full */ + _FDB_WRITE_STATUS(db, cur_sec_addr, status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_FULL, true); + sector->status = FDB_SECTOR_STORE_FULL; + /* calculate next sector address */ + if (sector->addr + db_sec_size(db) < db_max_size(db)) { + new_sec_addr = sector->addr + db_sec_size(db); + } + else if (db->rollover) { + new_sec_addr = 0; + } else { + /* not rollover */ + return FDB_SAVED_FULL; + } + read_sector_info(db, new_sec_addr, &db->cur_sec, false); + if (sector->status != FDB_SECTOR_STORE_EMPTY) { + /* calculate the oldest sector address */ + if (new_sec_addr + db_sec_size(db) < db_max_size(db)) { + db_oldest_addr(db) = new_sec_addr + db_sec_size(db); + } else { + db_oldest_addr(db) = 0; + } + format_sector(db, new_sec_addr); + read_sector_info(db, new_sec_addr, &db->cur_sec, false); + } + } else if (sector->status == FDB_SECTOR_STORE_FULL) { + /* database full */ + return FDB_SAVED_FULL; + } + + if (sector->status == FDB_SECTOR_STORE_EMPTY) { + /* change the sector to using */ + sector->status = FDB_SECTOR_STORE_USING; + sector->start_time = cur_time; + _FDB_WRITE_STATUS(db, sector->addr, status, FDB_SECTOR_STORE_STATUS_NUM, FDB_SECTOR_STORE_USING, true); + /* save the start timestamp */ + FLASH_WRITE(db, sector->addr + SECTOR_START_TIME_OFFSET, (uint32_t *)&cur_time, sizeof(fdb_time_t), true); + } + + return result; +} + +static fdb_err_t tsl_append(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t *timestamp) +{ + fdb_err_t result = FDB_NO_ERR; + fdb_time_t cur_time = timestamp == NULL ? db->get_time() : *timestamp; + + /* check the append length, MUST less than the db->max_len */ + if(blob->size > db->max_len) + { + FDB_INFO("Warning: append length (%" PRIdMAX ") is more than the db->max_len (%" PRIdMAX "). This tsl will be dropped.\n", + (intmax_t)blob->size, (intmax_t)(db->max_len)); + return FDB_WRITE_ERR; + } + + /* check the current timestamp, MUST more than the last save timestamp */ + if (cur_time <= db->last_time) { + FDB_INFO("Warning: current timestamp (%" PRIdMAX ") is less than or equal to the last save timestamp (%" PRIdMAX "). This tsl will be dropped.\n", + (intmax_t )cur_time, (intmax_t )(db->last_time)); + return FDB_WRITE_ERR; + } + + result = update_sec_status(db, &db->cur_sec, blob, cur_time); + if (result != FDB_NO_ERR) { + FDB_INFO("Error: update the sector status failed (%d)", result); + return result; + } + /* write the TSL node */ + result = write_tsl(db, blob, cur_time); + if (result != FDB_NO_ERR) { + FDB_INFO("Error: write tsl failed (%d)", result); + return result; + } + + /* recalculate the current using sector info */ + db->cur_sec.end_idx = db->cur_sec.empty_idx; + db->cur_sec.end_time = cur_time; + db->cur_sec.empty_idx += LOG_IDX_DATA_SIZE; + db->cur_sec.empty_data -= FDB_WG_ALIGN(blob->size); + db->cur_sec.remain -= LOG_IDX_DATA_SIZE + FDB_WG_ALIGN(blob->size); + db->last_time = cur_time; + + return result; +} + +/** + * Append a new log to TSDB. + * + * @param db database object + * @param blob log blob data + * + * @return result + */ +fdb_err_t fdb_tsl_append(fdb_tsdb_t db, fdb_blob_t blob) +{ + fdb_err_t result = FDB_NO_ERR; + + if (!db_init_ok(db)) { + FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db)); + return FDB_INIT_FAILED; + } + + db_lock(db); + result = tsl_append(db, blob, NULL); + db_unlock(db); + + return result; +} + +/** + * Append a new log to TSDB with specific timestamp. + * + * @param db database object + * @param blob log blob data + * + * @return result + */ +fdb_err_t fdb_tsl_append_with_ts(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t timestamp) +{ + fdb_err_t result = FDB_NO_ERR; + + if (!db_init_ok(db)) { + FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db)); + return FDB_INIT_FAILED; + } + + db_lock(db); + result = tsl_append(db, blob, ×tamp); + db_unlock(db); + + return result; +} + +/** + * The TSDB iterator for each TSL. + * + * @param db database object + * @param cb callback + * @param arg callback argument + */ +void fdb_tsl_iter(fdb_tsdb_t db, fdb_tsl_cb cb, void *arg) +{ + struct tsdb_sec_info sector; + uint32_t sec_addr, traversed_len = 0; + struct fdb_tsl tsl; + + if (!db_init_ok(db)) { + FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db)); + } + + if (cb == NULL) { + return; + } + + sec_addr = db_oldest_addr(db); + db_lock(db); + /* search all sectors */ + do { + traversed_len += db_sec_size(db); + if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) { + continue; + } + /* sector has TSL */ + if (sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL) { + if (sector.status == FDB_SECTOR_STORE_USING) { + /* copy the current using sector status */ + sector = db->cur_sec; + } + tsl.addr.index = sector.addr + SECTOR_HDR_DATA_SIZE; + /* search all TSL */ + do { + read_tsl(db, &tsl); + /* iterator is interrupted when callback return true */ + if (cb(&tsl, arg)) { + db_unlock(db); + return; + } + } while ((tsl.addr.index = get_next_tsl_addr(§or, &tsl)) != FAILED_ADDR); + } + } while ((sec_addr = get_next_sector_addr(db, §or, traversed_len)) != FAILED_ADDR); + db_unlock(db); +} + +/** + * The TSDB iterator for each TSL. + * + * @param db database object + * @param cb callback + * @param arg callback argument + */ +void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg) +{ + struct tsdb_sec_info sector; + uint32_t sec_addr, traversed_len = 0; + struct fdb_tsl tsl; + + if (!db_init_ok(db)) { + FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db)); + } + + if (cb == NULL) { + return; + } + + sec_addr = db->cur_sec.addr; + db_lock(db); + /* search all sectors */ + do { + traversed_len += db_sec_size(db); + if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) { + continue; + } + /* sector has TSL */ + if (sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL) { + if (sector.status == FDB_SECTOR_STORE_USING) { + /* copy the current using sector status */ + sector = db->cur_sec; + } + tsl.addr.index = sector.end_idx; + /* search all TSL */ + do { + read_tsl(db, &tsl); + /* iterator is interrupted when callback return true */ + if (cb(&tsl, cb_arg)) { + goto __exit; + } + } while ((tsl.addr.index = get_last_tsl_addr(§or, &tsl)) != FAILED_ADDR); + } else if (sector.status == FDB_SECTOR_STORE_EMPTY || sector.status == FDB_SECTOR_STORE_UNUSED) + goto __exit; + } while ((sec_addr = get_last_sector_addr(db, §or, traversed_len)) != FAILED_ADDR); + +__exit: + db_unlock(db); +} + +/* + * Found the matched TSL address. + */ +static int search_start_tsl_addr(fdb_tsdb_t db, int start, int end, fdb_time_t from, fdb_time_t to) +{ + struct fdb_tsl tsl; + while (true) { + tsl.addr.index = start + FDB_ALIGN((end - start) / 2, LOG_IDX_DATA_SIZE); + read_tsl(db, &tsl); + if (tsl.time < from) { + start = tsl.addr.index + LOG_IDX_DATA_SIZE; + } else if (tsl.time > from) { + end = tsl.addr.index - LOG_IDX_DATA_SIZE; + } else { + return tsl.addr.index; + } + + if (start > end) { + if (from > to) { + tsl.addr.index = start; + read_tsl(db, &tsl); + if (tsl.time > from) { + start -= LOG_IDX_DATA_SIZE; + } + } + break; + } + } + return start; +} + +/** + * The TSDB iterator for each TSL by timestamp. + * + * @param db database object + * @param from starting timestamp. It will be a reverse iterator when ending timestamp less than starting timestamp + * @param to ending timestamp + * @param cb callback + * @param arg callback argument + */ +void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg) +{ + struct tsdb_sec_info sector; + uint32_t sec_addr, start_addr, traversed_len = 0; + struct fdb_tsl tsl; + bool found_start_tsl = false; + + uint32_t (*get_sector_addr)(fdb_tsdb_t , tsdb_sec_info_t , uint32_t); + uint32_t (*get_tsl_addr)(tsdb_sec_info_t , fdb_tsl_t); + + if (!db_init_ok(db)) { + FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db)); + } + + if(from <= to) { + start_addr = db_oldest_addr(db); + get_sector_addr = get_next_sector_addr; + get_tsl_addr = get_next_tsl_addr; + } else { + start_addr = db->cur_sec.addr; + get_sector_addr = get_last_sector_addr; + get_tsl_addr = get_last_tsl_addr; + } + +// FDB_INFO("from %s", ctime((const time_t * )&from)); +// FDB_INFO("to %s", ctime((const time_t * )&to)); + + if (cb == NULL) { + return; + } + + sec_addr = start_addr; + db_lock(db); + /* search all sectors */ + do { + traversed_len += db_sec_size(db); + if (read_sector_info(db, sec_addr, §or, false) != FDB_NO_ERR) { + continue; + } + /* sector has TSL */ + if ((sector.status == FDB_SECTOR_STORE_USING || sector.status == FDB_SECTOR_STORE_FULL)) { + if (sector.status == FDB_SECTOR_STORE_USING) { + /* copy the current using sector status */ + sector = db->cur_sec; + } + if ((found_start_tsl) + || (!found_start_tsl && + ((from <= to && ((sec_addr == start_addr && from <= sector.start_time) || from <= sector.end_time)) || + (from > to && ((sec_addr == start_addr && from >= sector.end_time) || from >= sector.start_time))) + )) { + uint32_t start = sector.addr + SECTOR_HDR_DATA_SIZE, end = sector.end_idx; + + found_start_tsl = true; + /* search the first start TSL address */ + tsl.addr.index = search_start_tsl_addr(db, start, end, from, to); + /* search all TSL */ + do { + read_tsl(db, &tsl); + if (tsl.status != FDB_TSL_UNUSED) { + if ((from <= to && tsl.time >= from && tsl.time <= to) + || (from > to && tsl.time <= from && tsl.time >= to)) { + /* iterator is interrupted when callback return true */ + if (cb(&tsl, cb_arg)) { + goto __exit; + } + } else { + goto __exit; + } + } + } while ((tsl.addr.index = get_tsl_addr(§or, &tsl)) != FAILED_ADDR); + } + } else if (sector.status == FDB_SECTOR_STORE_EMPTY) { + goto __exit; + } + } while ((sec_addr = get_sector_addr(db, §or, traversed_len)) != FAILED_ADDR); + +__exit: + db_unlock(db); +} + +static bool query_count_cb(fdb_tsl_t tsl, void *arg) +{ + struct query_count_args *args = arg; + + if (tsl->status == args->status) { + args->count++; + } + + return false; +} + +/** + * Query some TSL's count by timestamp and status. + * + * @param db database object + * @param from starting timestamp + * @param to ending timestamp + * @param status status + */ +size_t fdb_tsl_query_count(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_status_t status) +{ + struct query_count_args arg = { FDB_TSL_UNUSED, 0 }; + + arg.status = status; + + if (!db_init_ok(db)) { + FDB_INFO("Error: TSL (%s) isn't initialize OK.\n", db_name(db)); + return 0; + } + + fdb_tsl_iter_by_time(db, from, to, query_count_cb, &arg); + + return arg.count; + +} + +/** + * Set the TSL status. + * + * @param db database object + * @param tsl TSL object + * @param status status + * + * @return result + */ +fdb_err_t fdb_tsl_set_status(fdb_tsdb_t db, fdb_tsl_t tsl, fdb_tsl_status_t status) +{ + fdb_err_t result = FDB_NO_ERR; + uint8_t status_table[TSL_STATUS_TABLE_SIZE]; + + /* write the status will by write granularity */ + _FDB_WRITE_STATUS(db, tsl->addr.index, status_table, FDB_TSL_STATUS_NUM, status, true); + + return result; +} + +/** + * Convert the TSL object to blob object + * + * @param tsl TSL object + * @param blob blob object + * + * @return new blob object + */ +fdb_blob_t fdb_tsl_to_blob(fdb_tsl_t tsl, fdb_blob_t blob) +{ + blob->saved.addr = tsl->addr.log; + blob->saved.meta_addr = tsl->addr.index; + blob->saved.len = tsl->log_len; + + return blob; +} + +static bool check_sec_hdr_cb(tsdb_sec_info_t sector, void *arg1, void *arg2) +{ + struct check_sec_hdr_cb_args *arg = arg1; + fdb_tsdb_t db = arg->db; + + if (!sector->check_ok) { + FDB_INFO("Sector (0x%08" PRIX32 ") header info is incorrect.\n", sector->addr); + (arg->check_failed) = true; + return true; + } else if (sector->status == FDB_SECTOR_STORE_USING) { + if (db->cur_sec.addr == FDB_DATA_UNUSED) { + memcpy(&db->cur_sec, sector, sizeof(struct tsdb_sec_info)); + } else { + FDB_INFO("Warning: Sector status is wrong, there are multiple sectors in use.\n"); + (arg->check_failed) = true; + return true; + } + } else if (sector->status == FDB_SECTOR_STORE_EMPTY) { + (arg->empty_num) += 1; + arg->empty_addr = sector->addr; + if ((arg->empty_num) == 1 && db->cur_sec.addr == FDB_DATA_UNUSED) { + memcpy(&db->cur_sec, sector, sizeof(struct tsdb_sec_info)); + } + } + + return false; +} +static bool format_all_cb(tsdb_sec_info_t sector, void *arg1, void *arg2) +{ + fdb_tsdb_t db = arg1; + + format_sector(db, sector->addr); + + return false; +} + +static void tsl_format_all(fdb_tsdb_t db) +{ + struct tsdb_sec_info sector; + + sector.addr = 0; + sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, db, NULL, format_all_cb, false); + db_oldest_addr(db) = 0; + db->cur_sec.addr = 0; + db->last_time = 0; + /* read the current using sector info */ + read_sector_info(db, db->cur_sec.addr, &db->cur_sec, false); + + FDB_INFO("All sector format finished.\n"); +} + +/** + * Clean all the data in the TSDB. + * + * @note It's DANGEROUS. This operation is not reversible. + * + * @param db database object + */ +void fdb_tsl_clean(fdb_tsdb_t db) +{ + db_lock(db); + tsl_format_all(db); + db_unlock(db); +} + +/** + * This function will get or set some options of the database + * + * @param db database object + * @param cmd the control command + * @param arg the argument + */ +void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg) +{ + FDB_ASSERT(db); + + switch (cmd) { + case FDB_TSDB_CTRL_SET_SEC_SIZE: + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.sec_size = *(uint32_t *)arg; + break; + case FDB_TSDB_CTRL_GET_SEC_SIZE: + *(uint32_t *)arg = db->parent.sec_size; + break; + case FDB_TSDB_CTRL_SET_LOCK: +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + db->parent.lock = (void (*)(fdb_db_t db))arg; +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + break; + case FDB_TSDB_CTRL_SET_UNLOCK: +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + db->parent.unlock = (void (*)(fdb_db_t db))arg; +#if !defined(__ARMCC_VERSION) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + break; + case FDB_TSDB_CTRL_SET_ROLLOVER: + /* this change MUST after database initialized */ + FDB_ASSERT(db->parent.init_ok == true); + db->rollover = *(bool *)arg; + break; + case FDB_TSDB_CTRL_GET_ROLLOVER: + *(bool *)arg = db->rollover; + break; + case FDB_TSDB_CTRL_GET_LAST_TIME: + *(fdb_time_t *)arg = db->last_time; + break; + case FDB_TSDB_CTRL_SET_FILE_MODE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.file_mode = *(bool *)arg; +#else + FDB_INFO("Error: set file mode Failed. Please defined the FDB_USING_FILE_MODE macro."); +#endif + break; + case FDB_TSDB_CTRL_SET_MAX_SIZE: +#ifdef FDB_USING_FILE_MODE + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.max_size = *(uint32_t *)arg; +#endif + break; + case FDB_TSDB_CTRL_SET_NOT_FORMAT: + /* this change MUST before database initialization */ + FDB_ASSERT(db->parent.init_ok == false); + db->parent.not_formatable = *(bool *)arg; + break; + } +} + +/** + * The time series database initialization. + * + * @param db database object + * @param name database name + * @param path FAL mode: partition name, file mode: database saved directory path + * @param get_time get current time function + * @param max_len maximum length of each log + * @param user_data user data + * + * @return result + */ +fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *path, fdb_get_time get_time, size_t max_len, void *user_data) +{ + fdb_err_t result = FDB_NO_ERR; + struct tsdb_sec_info sector; + struct check_sec_hdr_cb_args check_sec_arg = { db, false, 0, 0}; + + FDB_ASSERT(get_time); + + result = _fdb_init_ex((fdb_db_t)db, name, path, FDB_DB_TYPE_TS, user_data); + if (result != FDB_NO_ERR) { + goto __exit; + } + + /* lock the TSDB */ + db_lock(db); + + db->get_time = get_time; + db->max_len = max_len; + /* default rollover flag is true */ + db->rollover = true; + db_oldest_addr(db) = FDB_DATA_UNUSED; + db->cur_sec.addr = FDB_DATA_UNUSED; + /* must less than sector size */ + FDB_ASSERT(max_len < db_sec_size(db)); + + /* check all sector header */ + sector.addr = 0; + sector_iterator(db, §or, FDB_SECTOR_STORE_UNUSED, &check_sec_arg, NULL, check_sec_hdr_cb, true); + /* format all sector when check failed */ + if (check_sec_arg.check_failed) { + if (db->parent.not_formatable) { + result = FDB_READ_ERR; + goto __exit; + } else { + tsl_format_all(db); + } + } else { + uint32_t latest_addr; + if (check_sec_arg.empty_num > 0) { + latest_addr = check_sec_arg.empty_addr; + } else { + if (db->rollover) { + latest_addr = db->cur_sec.addr; + } else { + /* There is no empty sector. */ + latest_addr = db->cur_sec.addr = db_max_size(db) - db_sec_size(db); + } + } + /* db->cur_sec is the latest sector, and the next is the oldest sector */ + if (latest_addr + db_sec_size(db) >= db_max_size(db)) { + /* db->cur_sec is the the bottom of the database */ + db_oldest_addr(db) = 0; + } else { + db_oldest_addr(db) = latest_addr + db_sec_size(db); + } + } + FDB_DEBUG("TSDB (%s) oldest sectors is 0x%08" PRIX32 ", current using sector is 0x%08" PRIX32 ".\n", db_name(db), db_oldest_addr(db), + db->cur_sec.addr); + /* read the current using sector info */ + read_sector_info(db, db->cur_sec.addr, &db->cur_sec, true); + /* get last save time */ + if (db->cur_sec.status == FDB_SECTOR_STORE_USING) { + db->last_time = db->cur_sec.end_time; + } else if (db->cur_sec.status == FDB_SECTOR_STORE_EMPTY && db_oldest_addr(db) != db->cur_sec.addr) { + struct tsdb_sec_info sec; + uint32_t addr = db->cur_sec.addr; + + if (addr == 0) { + addr = db_max_size(db) - db_sec_size(db); + } else { + addr -= db_sec_size(db); + } + read_sector_info(db, addr, &sec, false); + db->last_time = sec.end_time; + } + + /* unlock the TSDB */ + db_unlock(db); + +__exit: + + _fdb_init_finish((fdb_db_t)db, result); + + return result; +} + +/** + * The time series database deinitialization. + * + * @param db database object + * + * @return result + */ +fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db) +{ + _fdb_deinit((fdb_db_t) db); + + return FDB_NO_ERR; +} + +#endif /* defined(FDB_USING_TSDB) */ diff --git a/User/lib/flashdb/fdb_utils.c b/User/lib/flashdb/fdb_utils.c new file mode 100644 index 0000000..2e2b99c --- /dev/null +++ b/User/lib/flashdb/fdb_utils.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief utils + * + * Some utils for this library. + */ + +#include +#include +#include +#include + +#define FDB_LOG_TAG "[utils]" + +static const uint32_t crc32_table[] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/** + * Calculate the CRC32 value of a memory buffer. + * + * @param crc accumulated CRC32 value, must be 0 on first call + * @param buf buffer to calculate CRC32 value for + * @param size bytes in buffer + * + * @return calculated CRC32 value + */ +uint32_t fdb_calc_crc32(uint32_t crc, const void *buf, size_t size) +{ + const uint8_t *p; + + p = (const uint8_t *)buf; + crc = crc ^ ~0U; + + while (size--) { + crc = crc32_table[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + } + + return crc ^ ~0U; +} + +size_t _fdb_set_status(uint8_t status_table[], size_t status_num, size_t status_index) +{ + size_t byte_index = SIZE_MAX; + /* + * | write garn | status0 | status1 | status2 | status3 | + * ------------------------------------------------------------------------------------------------------ + * | 1bit | 0xFF | 0x7F | 0x3F | 0x1F + * ------------------------------------------------------------------------------------------------------ + * | 8bit | 0xFF FF FF | 0x00 FF FF | 0x00 00 FF | 0x00 00 00 + * ------------------------------------------------------------------------------------------------------ + * | 32bit | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF 00FFFFFF | 0x00FFFFFF 00FFFFFF + * | | 0xFFFFFFFF | 0xFFFFFFFF | 0xFFFFFFFF | 0x00FFFFFF + * ------------------------------------------------------------------------------------------------------ + * | | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF + * | 64bit | 0xFFFFFFFF FFFFFFFF | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF + * | | 0xFFFFFFFF FFFFFFFF | 0xFFFFFFFF FFFFFFFF | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF + */ + memset(status_table, FDB_BYTE_ERASED, FDB_STATUS_TABLE_SIZE(status_num)); + if (status_index > 0) { +#if (FDB_WRITE_GRAN == 1) + byte_index = (status_index - 1) / 8; +#if (FDB_BYTE_ERASED == 0xFF) + status_table[byte_index] &= (0x00ff >> (status_index % 8)); +#else + status_table[byte_index] |= (0x00ff >> (status_index % 8)); +#endif +#else + byte_index = (status_index - 1) * (FDB_WRITE_GRAN / 8); + status_table[byte_index] = FDB_BYTE_WRITTEN; +#endif /* FDB_WRITE_GRAN == 1 */ + } + + return byte_index; +} + +size_t _fdb_get_status(uint8_t status_table[], size_t status_num) +{ + size_t i = 0, status_num_bak = --status_num; + + while (status_num --) { + /* get the first 0 position from end address to start address */ +#if (FDB_WRITE_GRAN == 1) + if ((status_table[status_num / 8] & (0x80 >> (status_num % 8))) == 0x00) { + break; + } +#else /* (FDB_WRITE_GRAN == 8) || (FDB_WRITE_GRAN == 32) || (FDB_WRITE_GRAN == 64) */ + if (status_table[status_num * FDB_WRITE_GRAN / 8] == FDB_BYTE_WRITTEN) { + break; + } +#endif /* FDB_WRITE_GRAN == 1 */ + i++; + } + + return status_num_bak - i; +} + +fdb_err_t _fdb_write_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t status_num, size_t status_index, bool sync) +{ + fdb_err_t result = FDB_NO_ERR; + size_t byte_index; + + FDB_ASSERT(status_index < status_num); + FDB_ASSERT(status_table); + + /* set the status first */ + byte_index = _fdb_set_status(status_table, status_num, status_index); + + /* the first status table value is all 1, so no need to write flash */ + if (byte_index == SIZE_MAX) { + return FDB_NO_ERR; + } +#if (FDB_WRITE_GRAN == 1) + result = _fdb_flash_write(db, addr + byte_index, (uint32_t *)&status_table[byte_index], 1, sync); +#else /* (FDB_WRITE_GRAN == 8) || (FDB_WRITE_GRAN == 32) || (FDB_WRITE_GRAN == 64) */ + /* write the status by write granularity + * some flash (like stm32 onchip) NOT supported repeated write before erase */ + result = _fdb_flash_write(db, addr + byte_index, (uint32_t *) &status_table[byte_index], FDB_WRITE_GRAN / 8, sync); +#endif /* FDB_WRITE_GRAN == 1 */ + + return result; +} + +size_t _fdb_read_status(fdb_db_t db, uint32_t addr, uint8_t status_table[], size_t total_num) +{ + FDB_ASSERT(status_table); + + _fdb_flash_read(db, addr, (uint32_t *) status_table, FDB_STATUS_TABLE_SIZE(total_num)); + + return _fdb_get_status(status_table, total_num); +} + +/* + * find the continue 0xFF flash address to end address + */ +uint32_t _fdb_continue_ff_addr(fdb_db_t db, uint32_t start, uint32_t end) +{ + uint8_t buf[32], last_data = FDB_BYTE_WRITTEN; + size_t i, addr = start, read_size; + + for (; start < end; start += sizeof(buf)) { + if (start + sizeof(buf) < end) { + read_size = sizeof(buf); + } else { + read_size = end - start; + } + _fdb_flash_read(db, start, (uint32_t *) buf, read_size); + for (i = 0; i < read_size; i++) { + if (last_data != FDB_BYTE_ERASED && buf[i] == FDB_BYTE_ERASED) { + addr = start + i; + } + last_data = buf[i]; + } + } + + if (last_data == FDB_BYTE_ERASED) { + return FDB_WG_ALIGN(addr); + } else { + return end; + } +} + +/** + * Make a blob object. + * + * @param blob blob object + * @param value_buf value buffer + * @param buf_len buffer length + * + * @return new blob object + */ +fdb_blob_t fdb_blob_make(fdb_blob_t blob, const void *value_buf, size_t buf_len) +{ + blob->buf = (void *)value_buf; + blob->size = buf_len; + + return blob; +} + +/** + * Read the blob object in database. + * + * @param db database object + * @param blob blob object + * + * @return read length + */ +size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob) +{ + size_t read_len = blob->size; + + if (read_len > blob->saved.len) { + read_len = blob->saved.len; + } + if (_fdb_flash_read(db, blob->saved.addr, blob->buf, read_len) != FDB_NO_ERR) { + read_len = 0; + } + + return read_len; +} + +#ifdef FDB_USING_FILE_MODE +extern fdb_err_t _fdb_file_read(fdb_db_t db, uint32_t addr, void *buf, size_t size); +extern fdb_err_t _fdb_file_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync); +extern fdb_err_t _fdb_file_erase(fdb_db_t db, uint32_t addr, size_t size); +#endif /* FDB_USING_FILE_LIBC */ + +fdb_err_t _fdb_flash_read(fdb_db_t db, uint32_t addr, void *buf, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return _fdb_file_read(db, addr, buf, size); +#else + return FDB_READ_ERR; +#endif + } else { +#ifdef FDB_USING_FAL_MODE + if (fal_partition_read(db->storage.part, addr, (uint8_t *) buf, size) < 0) { + result = FDB_READ_ERR; + } +#endif + } + + return result; +} + +fdb_err_t _fdb_flash_erase(fdb_db_t db, uint32_t addr, size_t size) +{ + fdb_err_t result = FDB_NO_ERR; + + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return _fdb_file_erase(db, addr, size); +#else + return FDB_ERASE_ERR; +#endif /* FDB_USING_FILE_MODE */ + } else { +#ifdef FDB_USING_FAL_MODE + if (fal_partition_erase(db->storage.part, addr, size) < 0) { + result = FDB_ERASE_ERR; + } +#endif + } + + return result; +} + +fdb_err_t _fdb_flash_write(fdb_db_t db, uint32_t addr, const void *buf, size_t size, bool sync) +{ + fdb_err_t result = FDB_NO_ERR; + + if (db->file_mode) { +#ifdef FDB_USING_FILE_MODE + return _fdb_file_write(db, addr, buf, size, sync); +#else + return FDB_READ_ERR; +#endif /* FDB_USING_FILE_MODE */ + } else { +#ifdef FDB_USING_FAL_MODE + if (fal_partition_write(db->storage.part, addr, (uint8_t *)buf, size) < 0) + { + result = FDB_WRITE_ERR; + } +#endif + } + + return result; + +} diff --git a/User/lib/flashdb/flashdb.h b/User/lib/flashdb/flashdb.h new file mode 100644 index 0000000..92816b2 --- /dev/null +++ b/User/lib/flashdb/flashdb.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020, Armink, + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public APIs. + */ + +#ifndef _FLASHDB_H_ +#define _FLASHDB_H_ + +#include +#include +#include +#include +#include +#include + +#ifdef FDB_USING_FAL_MODE +#include +#endif + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* FlashDB database API */ + fdb_err_t fdb_kvdb_init(fdb_kvdb_t db, const char *name, const char *path, struct fdb_default_kv *default_kv, + void *user_data); + void fdb_kvdb_control(fdb_kvdb_t db, int cmd, void *arg); + fdb_err_t fdb_kvdb_check(fdb_kvdb_t db); + fdb_err_t fdb_kvdb_deinit(fdb_kvdb_t db); + fdb_err_t fdb_tsdb_init(fdb_tsdb_t db, const char *name, const char *path, fdb_get_time get_time, size_t max_len, + void *user_data); + void fdb_tsdb_control(fdb_tsdb_t db, int cmd, void *arg); + fdb_err_t fdb_tsdb_deinit(fdb_tsdb_t db); + + /* blob API */ + fdb_blob_t fdb_blob_make(fdb_blob_t blob, const void *value_buf, size_t buf_len); + size_t fdb_blob_read(fdb_db_t db, fdb_blob_t blob); + + /* Key-Value API like a KV DB */ + fdb_err_t fdb_kv_set(fdb_kvdb_t db, const char *key, const char *value); + char *fdb_kv_get(fdb_kvdb_t db, const char *key); + fdb_err_t fdb_kv_set_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob); + size_t fdb_kv_get_blob(fdb_kvdb_t db, const char *key, fdb_blob_t blob); + fdb_err_t fdb_kv_del(fdb_kvdb_t db, const char *key); + fdb_kv_t fdb_kv_get_obj(fdb_kvdb_t db, const char *key, fdb_kv_t kv); + fdb_blob_t fdb_kv_to_blob(fdb_kv_t kv, fdb_blob_t blob); + fdb_err_t fdb_kv_set_default(fdb_kvdb_t db); + void fdb_kv_print(fdb_kvdb_t db); + fdb_kv_iterator_t fdb_kv_iterator_init(fdb_kvdb_t db, fdb_kv_iterator_t itr); + bool fdb_kv_iterate(fdb_kvdb_t db, fdb_kv_iterator_t itr); + + /* Time series log API like a TSDB */ + fdb_err_t fdb_tsl_append(fdb_tsdb_t db, fdb_blob_t blob); + fdb_err_t fdb_tsl_append_with_ts(fdb_tsdb_t db, fdb_blob_t blob, fdb_time_t timestamp); + void fdb_tsl_iter(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg); + void fdb_tsl_iter_reverse(fdb_tsdb_t db, fdb_tsl_cb cb, void *cb_arg); + void fdb_tsl_iter_by_time(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_cb cb, void *cb_arg); + size_t fdb_tsl_query_count(fdb_tsdb_t db, fdb_time_t from, fdb_time_t to, fdb_tsl_status_t status); + fdb_err_t fdb_tsl_set_status(fdb_tsdb_t db, fdb_tsl_t tsl, fdb_tsl_status_t status); + void fdb_tsl_clean(fdb_tsdb_t db); + fdb_blob_t fdb_tsl_to_blob(fdb_tsl_t tsl, fdb_blob_t blob); + + /* fdb_utils.c */ + uint32_t fdb_calc_crc32(uint32_t crc, const void *buf, size_t size); + + static inline void fdb_lock(fdb_db_t db) + { + __disable_irq(); + } + + static inline void fdb_unlock(fdb_db_t db) + { + __enable_irq(); + } + +#ifdef __cplusplus +} +#endif + +#endif /* _FLASHDB_H_ */ diff --git a/User/lib/flow/.vscode/c_cpp_properties.json b/User/lib/flow/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..ff92585 --- /dev/null +++ b/User/lib/flow/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "C:/TDM-GCC-64/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/User/lib/flow/.vscode/launch.json b/User/lib/flow/.vscode/launch.json new file mode 100644 index 0000000..da1e2e9 --- /dev/null +++ b/User/lib/flow/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "e:/work/stm32/epm/User/lib/flow", + "program": "e:/work/stm32/epm/User/lib/flow/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/User/lib/flow/.vscode/settings.json b/User/lib/flow/.vscode/settings.json new file mode 100644 index 0000000..104d25b --- /dev/null +++ b/User/lib/flow/.vscode/settings.json @@ -0,0 +1,58 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/Build/vcvarsall.bat", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false +} \ No newline at end of file diff --git a/User/lib/flow/README.md b/User/lib/flow/README.md new file mode 100644 index 0000000..f9fbfd2 --- /dev/null +++ b/User/lib/flow/README.md @@ -0,0 +1,244 @@ +# flow_lib + +#### 介绍 +适用于嵌入式单片机的裸机程序微库,只占用你的rom 6个字节,是的,6个字节。颠覆式的设计思维,让你写代码的时候像flow(流水)一样丝滑,让你永远不用在为delay时cpu空转而烦恼,附加的超轻便的软件定时器让你轻松实现各种定时需求,另还有信号量的配方,让你任务间的同步像诗一样写意,并且能让你裸机程序效率提升百倍以上。 + +#### 移植说明 +移植特别简单,flow_def.h有一个全局变量: +``` +extern unsigned long flow_tick; +``` + +把这个变量放在你的某个硬件中断里去,这个硬件中断一定要是一直运行的,推荐RTC半秒中断,或者systick中断都可以。 + +然后在flow.h里的第一行有个宏 +``` +#define FL_HARD_TICK (500) /* 系统硬件中断一次所需要的时间,单位ms */ +``` + +把这里的值改成你的硬件中断一次所需的时间,单位是毫秒,比如你的flow_tick放在了一个500ms中断一次的rtc里,那么这里的宏FL_HARD_TICK的值就是500,具体中断设为多少取决于你的系统最短一次的延时的时间。 + +假如我的最短延时需求是100ms,那么我就得给个100ms中断一次的硬件中断源,宏FL_HARD_TICK的值就是100,我就可以这样使用: +``` +FL_LOCK_DELAY(fl, FL_CLOCK_SEC /10); +``` +来延时100ms。 + +#### 使用说明 +核心文件时flow.h,看这里的注释基本就会使用大部分功能。 + +``` +#ifndef __FLOW_ +#define __FLOW_ + +#include +#include +#include + +#define FL_HARD_TICK (500) /* 系统硬件中断一次所需要的时间,单位ms */ +#define FL_CLOCK_SEC (1000/FL_HARD_TICK) /* 一秒钟需要的tick,可以除也可以自行添加其它宏 */ + +/** + * 初始化一个flow进程 + */ +#define FL_INIT(fl) FLOW_INIT(fl) + +/** + * flow头,必须放在函数内的最前面 + */ +#define FL_HEAD(fl) FLOW_HEAD(fl) + +/** + * flow尾,必须放在函数内的最后面 + */ +#define FL_TAIL(fl) FLOW_TAIL(fl) + +/** + * 给进程加锁,直到judge为真,加锁期间一直放开cpu给其他进程使用 + */ +#define FL_LOCK_WAIT(fl, judge) FLOW_LOCK_WAIT(fl, judge) + +/** + * 如果judge为真,就一直给进程加锁,加锁期间一直放开cpu给其他进程使用 + */ +#define FL_LOCK_WHILE(fl, judge) FLOW_LOCK_WHILE(fl, judge) + +/** + * 退出该进程 + */ +#define FL_EXIT(fl) FLOW_EXIT(fl) + +/** + * 无条件锁住进程一次,下次进来再接着往下运行 + */ +#define FL_LOCK_ONCE(fl) FLOW_LOCK_ONCE(fl) + +/** + * 等待一个flow进程结束 + */ +#define FL_WAIT_PROCESS_END(fl, process) FLOW_WAIT_PROCESS_END(fl, process) + +/** + * 等待一个flow子进程结束 + */ +#define FL_WAIT_CHILD(fl, cfl, process) FLOW_WAIT_CHILD_PROCESS_END(fl, cfl, process) + +/** + * 给进程加锁,时长为time,加锁期间一直放开cpu给其他进程使用,time如果用FL_CLOCK_SEC来乘,那么time的单位就是s + * 此处time必须是常数 + */ +#define FL_LOCK_DELAY(fl,time) FLOW_LOCK_DELAY(fl,time) + +/** + * 给进程加锁,时长为time,延时期间如果judge为真,就直接解锁进程 + * 此处time必须是常数 + */ +#define FL_LOCK_DELAY_OR_WAIT(fl,judge,time) FLOW_LOCK_DELAY_OR_WAIT(fl,judge,time) + +/** + * 初始化一个信号量 + */ +#define FL_SEM_INIT(sem, count) FLOW_SEM_INIT(sem, count) + +/** + * 给进程加锁,直到有信号释放 + */ +#define FL_LOCK_WAIT_SEM(f, sem) FLOW_LOCK_WAIT_SEM(f, sem) + +/** + * 给进程加锁,直到有信号或者超时,此处time可以为变量,其他的接口处time必须是常数 + */ +#define FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time) FLOW_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time) + +/** + * 释放一个信号量 + */ +#define FL_SEM_RELEASE(sem) FLOW_SEM_RELEASE(sem) + +/** + * 初始化一个软件定时器 + */ +void fl_timer_set(struct flow_timer *t, unsigned long interval); + +/** + * 复位一个软件定时器 + */ +void fl_timer_reset(struct flow_timer *t); + +/** + * 重启一个软件定时器 + */ +void fl_timer_restart(struct flow_timer *t); + +/** + * 检测一个软件定时器是否超时,0为不超时,1为超时 + */ +char fl_timer_timeout(struct flow_timer *t); + +/** + * 检测一个软件定时器还剩多少时间超时,单位为硬件tick,比如硬件tick 500ms中断一次,那么 + * 返回的时间单位就是500ms + */ +unsigned long fl_hour_much_time(struct flow_timer *t); + +#endif /* __FLOW_ */ +``` + + +简单举个例子,先从需求说起,假如说你现在需要一个函数,这个函数的功能是每隔1s让你的led亮一次,正常设计的要么起个软件定时器或者硬件定时器,甚至状态机可以实现需求,但是都太low了,让我们看一下如何用flow库来实现这个函数。 + +该函数格式如下: + +``` +char led_flash(struct flow *fl) +{} +``` +其中char、struct flow *fl是必备的。 + +再来看看函数里面的内容格式: + +``` +char led_flash(struct flow *fl) +{ + FL_HEAD(fl); + FL_TAIL(fl); +} +``` +函数里面的FL_HEAD和FL_TAIL是使用flow库的所必须的宏,FL_HEAD(fl)放到函数的最前面,如果你的函数内部有变量定义的话放在变量定义的后面。而FL_TAIL(fl)是放在函数最后面一行的。 + +基本格式有了,再来看下如何实现延时一秒呢?其实只用一个语句就OK。 + +``` +char led_flash(struct flow *fl) +{ + FL_HEAD(fl); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); + led_open(); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); + led_close(); + FL_TAIL(fl); +} +``` + +是的,你没看错,仅仅只需要FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1)这一个语句就OK,当执行到这个语句的时候该函数就会让出CPU权限,当延时时间到了之后,就会回来接着执行FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1)下面的语句。一直到FL_TAIL(fl),该函数就会结束任务,再也不会执行了,那么如果我们想让它一直循环执行呢?看下面: + +``` +char led_flash(struct flow *fl) +{ + FL_HEAD(fl); + while(1) + { + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); + led_open(); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); + led_close(); + } + FL_TAIL(fl); +} +``` +看起来像不像个进程?其实也有点操作系统的样子了。。。 + +光有这个函数也不行,还得进行一些额外的操作 + +比如: + +``` +static struct flow fl_led; /* 1,定义一个struct flow变量给这个函数使用 */ + +static char led_flash(struct flow *fl) +{ + FL_HEAD(fl); + led_init(); /* 这里还能解决你的初始化问题,这里的函数只会在开机时或者说进程第一次进来时运行一次,以后将永远不会运行。注意:如果放在 + FL_HEAD(fl)前面,那么就是每次轮到这个进程运行的时侯就会运行一次,总之很灵活 */ + while(1) + { + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); + led_open(); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); + led_close(); + } + FL_TAIL(fl); +} + +int main(void) +{ + FL_INIT(&fl_led); /* 2,初始化struct flow变量 */ + while(1) + { + led_flash(&fl_led); /* 3,把led_flash进程放在main函数的while循环里 */ + ... + } + return 0; +} +``` +经过以上3步,就可以实现进程之间的切换啦。然后想根据某个条件来锁住线程释放CPU的话,可以把里面的 +``` +FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1); +``` +换成 +``` +FL_LOCK_WAIT(fl, judge); +``` +当里面的judge为假时线程就一直锁住在这一行语句,当judge为真时就可以往下执行啦。同理可以完成很多其他的神奇功能,让你的cpu再也不空转啦,具体请看flow.h文件。。。。 + +这个版本暂时先写这么多,先看看example.c。 diff --git a/User/lib/flow/example.c b/User/lib/flow/example.c new file mode 100644 index 0000000..ef0ecc4 --- /dev/null +++ b/User/lib/flow/example.c @@ -0,0 +1,28 @@ +#include "flow.h" + +/* 1,初始化一个struct flow变量 */ +static struct flow fl_led; + +static char led_flash(struct flow *fl) +{ + FL_HEAD(fl); + for (;;) + { + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1U); /* 延时一秒 */ + led_open(); + FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1U); /* 延时一秒 */ + led_close(); + } + FL_TAIL(fl); +} + +int main(void) +{ + FL_INIT(&fl_led); + for (;;) + { + led_flash(&fl_led); + // other_process(); + } + return 0; +} diff --git a/User/lib/flow/flow.h b/User/lib/flow/flow.h new file mode 100644 index 0000000..30e6401 --- /dev/null +++ b/User/lib/flow/flow.h @@ -0,0 +1,129 @@ +/** + * @file flow.h + * @author: xxx + * @date: 2023-07-21 17:00:15 + * @brief + * @copyright: Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __FLOW_ +#define __FLOW_ + +#include "flow_def.h" +#include "flow_core.h" +#include "flow_sem.h" + +#define FL_HARD_TICK (10U) /* 系统硬件中断一次所需要的时间,单位ms */ +#define FL_CLOCK_SEC (1000U / FL_HARD_TICK) /* 一秒钟需要的tick,可以根据需求添加其他时间更短的宏 */ +#define FL_CLOCK_100MSEC (100U / FL_HARD_TICK) +#define FL_CLOCK_10MSEC (FL_CLOCK_100MSEC / 10U) + +/** + * 初始化一个flow进程 + */ +#define FL_INIT(fl) FLOW_INIT((fl)) + +/** + * flow头,必须放在函数内的最前面 + */ +#define FL_HEAD(fl) FLOW_HEAD((fl)) + +/** + * flow尾,必须放在函数内的最后面 + */ +#define FL_TAIL(fl) FLOW_TAIL((fl)) + +/** + * 给进程加锁,直到judge为真,加锁期间一直放开cpu给其他进程使用 + */ +#define FL_LOCK_WAIT(fl, judge) FLOW_LOCK_WAIT((fl), (judge)) + +/** + * 如果judge为真,就一直给进程加锁,加锁期间一直放开cpu给其他进程使用 + */ +#define FL_LOCK_WHILE(fl, judge) FLOW_LOCK_WHILE((fl), (judge)) + +/** + * 退出该进程 + */ +#define FL_EXIT(fl) FLOW_EXIT((fl)) + +/** + * 无条件锁住进程一次,下次进来再接着往下运行 + */ +#define FL_LOCK_ONCE(fl) FLOW_LOCK_ONCE((fl)) + +/** + * 等待一个flow进程结束 + */ +#define FL_WAIT_PROCESS_END(fl, process) FLOW_WAIT_PROCESS_END((fl), (process)) + +/** + * 等待一个flow子进程结束 + */ +#define FL_WAIT_CHILD(fl, cfl, process) FLOW_WAIT_CHILD_PROCESS_END((fl), (cfl), (process)) + +/** + * 给进程加锁,时长为time,加锁期间一直放开cpu给其他进程使用,time如果用FL_CLOCK_SEC来乘,那么time的单位就是s + * 此处time必须是常数 + */ +#define FL_LOCK_DELAY(fl, time) FLOW_LOCK_DELAY((fl), (time)) + +/** + * 给进程加锁,时长为time,延时期间如果judge为真,就直接解锁进程 + * 此处time必须是常数 + */ +#define FL_LOCK_DELAY_OR_WAIT(fl, judge, time) FLOW_LOCK_DELAY_OR_WAIT((fl), (judge), (time)) + +/** + * 初始化一个信号量 + */ +#define FL_SEM_INIT(sem, count) FLOW_SEM_INIT((sem), (count)) + +/** + * 给进程加锁,直到有信号释放 + */ +#define FL_LOCK_WAIT_SEM(fl, sem) FLOW_LOCK_WAIT_SEM((fl), (sem)) + +/** + * 给进程加锁,直到有信号或者超时,此处time可以为常数或者变量,其他的接口处time必须是常数 + */ +#define FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time) FLOW_LOCK_WAIT_SEM_OR_TIMEOUT((fl), (sem), (time)) + +/** + * 释放一个信号量 + */ +#define FL_SEM_RELEASE(sem) FLOW_SEM_RELEASE((sem)) + +/** + * 检测一个信号量是否被释放 + */ +#define FL_SEM_IS_RELEASE(fl, sem) FLOW_SEM_IS_RELEASE((fl), (sem)) + +/** + * 初始化一个软件定时器 + */ +void fl_timer_set(struct flow_timer *t, unsigned long interval); + +/** + * 复位一个软件定时器 + */ +void fl_timer_reset(struct flow_timer *t); + +/** + * 重启一个软件定时器 + */ +void fl_timer_restart(struct flow_timer *t); + +/** + * 检测一个软件定时器是否超时,0为不超时,1为超时 + */ +unsigned char fl_timer_timeout(struct flow_timer *t); + +/** + * 检测一个软件定时器还剩多少时间超时,单位为硬件tick,比如硬件tick 500ms中断一次,那么 + * 返回的剩余时间就是500ms*n + */ +unsigned long fl_hour_much_time(struct flow_timer *t); + +#endif /* __FLOW_ */ diff --git a/User/lib/flow/flow_core.c b/User/lib/flow/flow_core.c new file mode 100644 index 0000000..87bb5bd --- /dev/null +++ b/User/lib/flow/flow_core.c @@ -0,0 +1,83 @@ +/** + * @file + * @author xxx + * @date 2023-07-21 17:00:15 + * @brief + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "flow.h" + +unsigned long flow_tick; + +/** + * @brief 设置流量计器的间隔时间。 + * @param t 要设置的流量计器。 + * @param interval 要设置的间隔时间值。 + * @return 如果间隔时间无效或无法设置,则返回NULL。 + * @note 此函数设置间隔时间并重置计时器,因此它将在下一个间隔时间 occurs时开始。 + */ +void fl_timer_set(struct flow_timer *t, unsigned long interval) +{ + if (interval == 0) + { + // 如果间隔时间为零,返回错误 + return; + } + + t->interval = interval; + t->start = flow_tick; +} + +/** + * @brief 重置流量计器。 + * @param t 要重置的流量计器。 + * @return 如果无法重置计时器,则返回NULL。 + * @note 此函数将计时器的开始时间加上间隔时间,因此它将在下一个间隔时间 occurs时开始。 + */ +void fl_timer_reset(struct flow_timer *t) +{ + t->start += t->interval; +} + +/** + * @brief 重新启动流量计器。 + * @param t 要重新启动的流量计器。 + * @return 如果无法重新启动计时器,则返回NULL。 + * @note 此函数将计时器的开始时间设置为当前flow_tick,因此它将在重新开始时从基本开始。 + */ +void fl_timer_restart(struct flow_timer *t) +{ + t->start = flow_tick; +} + +/** + * @brief 检查给定的flow_timer结构体的超时状态 + * @param {flow_timer} *t 指向flow_timer结构体的指针 + * @return {unsigned char} 超时返回1,否则返回0 + * @note 检查当前时间与flow_timer结构体中的start时间之差是否大于或等于interval + */ +unsigned char fl_timer_timeout(struct flow_timer *t) +{ + return ((flow_tick - t->start) >= t->interval) ? 1U : 0U; +} + +/** + * @brief 计算给定flow_timer结构体中的时间长度 + * @param {flow_timer} *t 指向flow_timer结构体的指针 + * @return {unsigned long} 返回时间长度 + * @note 计算start时间加上interval与当前时间flow_tick之差,如果大于等于flow_tick,则返回time_len - flow_tick,否则返回0 + */ +unsigned long fl_hour_much_time(struct flow_timer *t) +{ + unsigned long time_len = t->start + t->interval; + + if (time_len >= flow_tick) + { + return (time_len - flow_tick); + } + else + { + return 0U; + } +} diff --git a/User/lib/flow/flow_core.h b/User/lib/flow/flow_core.h new file mode 100644 index 0000000..b6857a3 --- /dev/null +++ b/User/lib/flow/flow_core.h @@ -0,0 +1,106 @@ +/** + * @file flow_core.h + * @author: xxx + * @date: 2023-07-21 17:00:15 + * @brief + * @copyright: Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __FLOW_CORE_ +#define __FLOW_CORE_ + +#include "flow_def.h" + +// 在定时器中断中调用 +#define FLOW_TICK_UPDATE() \ + do \ + { \ + flow_tick++; \ + } while (0); + +// 初始化一个flow进程 +#define FLOW_INIT(f) ((f)->line = 0) + +// flow头,必须放在函数内的最前面 +#define FLOW_HEAD(f) \ + { \ + volatile char lock_once_flag = 0; \ + switch ((f)->line) \ + { \ + case 0: +// flow尾,必须放在函数内的最后面 +#define FLOW_TAIL(f) \ + } \ + ; \ + lock_once_flag = (f)->line = 0; \ + return FLOW_END; \ + } \ + ; + +// 给进程加锁,直到judge为真,加锁期间一直放开cpu给其他进程使用 +#define FLOW_LOCK_WAIT(f, judge) \ + do \ + { \ + (f)->line = __LINE__; \ + case __LINE__:; \ + if (!(judge)) \ + return FLOW_WAIT; \ + } while (0) + +// 如果judge为真,就一直给进程加锁,加锁期间一直放开cpu给其他进程使用 +#define FLOW_LOCK_WHILE(f, judge) \ + do \ + { \ + (f)->line = __LINE__; \ + case __LINE__:; \ + if (judge) \ + return FLOW_WAIT; \ + } while (0) + +// 退出该进程 +#define FLOW_EXIT(f) \ + do \ + { \ + (f)->line = 0; \ + return FLOW_FINISH; \ + } while (0) + +// 无条件锁住进程一次,下次进来再接着往下运行 +#define FLOW_LOCK_ONCE(f) \ + do \ + { \ + lock_once_flag = 1; \ + (f)->line = __LINE__; \ + case __LINE__:; \ + if (lock_once_flag) \ + return FLOW_LOCK; \ + } while (0) + +// 等待一个flow进程结束 +#define FLOW_WAIT_PROCESS_END(f, process) FLOW_LOCK_WHILE(f, (process) < FLOW_FINISH) + +// 等待一个flow子进程结束 +#define FLOW_WAIT_CHILD_PROCESS_END(f, cf, process) \ + do \ + { \ + FLOW_INIT((cf)); \ + FLOW_WAIT_PROCESS_END((f), (process)); \ + } while (0) + +// 给进程加锁,时长为time,加锁期间一直放开cpu给其他进程使用,time如果用FL_CLOCK_SEC来乘,那么time的单位就是s +#define FLOW_LOCK_DELAY(f, t) \ + do \ + { \ + (f)->time = flow_tick; \ + FLOW_LOCK_WAIT((f), ((flow_tick - (f)->time) >= (t))); \ + } while (0) + +// 给进程加锁,时长为time,延时期间如果judge为真,就直接解锁进程 +#define FLOW_LOCK_DELAY_OR_WAIT(f, judge, t) \ + do \ + { \ + (f)->time = flow_tick; \ + FLOW_LOCK_WAIT((f), ((judge) || ((flow_tick - (f)->time) >= (t)))); \ + } while (0) + +#endif /* __FLOW_CORE_ */ diff --git a/User/lib/flow/flow_def.h b/User/lib/flow/flow_def.h new file mode 100644 index 0000000..1537877 --- /dev/null +++ b/User/lib/flow/flow_def.h @@ -0,0 +1,37 @@ +/** + * @file flow_def.h + * @author: xxx + * @date: 2023-07-21 17:00:15 + * @brief + * @copyright: Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __FLOW_DEF_ +#define __FLOW_DEF_ + +#define FLOW_WAIT (0) +#define FLOW_LOCK (1) +#define FLOW_FINISH (2) +#define FLOW_END (3) + +struct flow +{ + unsigned long line; + unsigned long time; +}; + +struct flow_timer +{ + unsigned long start; + unsigned long interval; +}; + +struct flow_sem +{ + unsigned long count; + unsigned long time; +}; + +extern unsigned long flow_tick; + +#endif /* __FLOW_DEF_ */ diff --git a/User/lib/flow/flow_sem.h b/User/lib/flow/flow_sem.h new file mode 100644 index 0000000..b524683 --- /dev/null +++ b/User/lib/flow/flow_sem.h @@ -0,0 +1,40 @@ +/*** + * @file: + * @author: xxx + * @date: 2023-07-21 17:00:15 + * @brief + * @copyright: Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __FLOW_SEM_H__ +#define __FLOW_SEM_H__ + +#include "flow_def.h" +#include "flow_core.h" + +#define FLOW_SEM_INIT(s, c) ((s)->count = c) // 初始化信号量s的计数值为c + +// 等待信号量s的计数值大于0 +#define FLOW_LOCK_WAIT_SEM(f, s) \ + do \ + { \ + FLOW_LOCK_WAIT(f, (s)->count > 0); \ + --(s)->count; \ + } while (0) + +// 等待信号量s的计数值大于0,或者当前时间与锁f的时间之差大于等于t +#define FLOW_LOCK_WAIT_SEM_OR_TIMEOUT(f, s, t) \ + do \ + { \ + (f)->time = flow_tick; \ + (s)->time = (t); \ + FLOW_LOCK_WAIT(f, (((s)->count > 0) || ((flow_tick - (f)->time) >= ((s)->time)))); \ + if (((s)->count > 0) && ((flow_tick - (f)->time) < ((s)->time))) \ + --(s)->count; \ + } while (0) + +#define FLOW_SEM_RELEASE(s) (++(s)->count) + +#define FLOW_SEM_IS_RELEASE(f, s) (flow_tick - (f)->time) < ((s)->time) + +#endif /* __FLOW_SEM_H__ */ diff --git a/User/lib/inc/aes.h b/User/lib/inc/aes.h new file mode 100644 index 0000000..7c2a92c --- /dev/null +++ b/User/lib/inc/aes.h @@ -0,0 +1,161 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state. + */ + +#ifndef AES_H +#define AES_H + +#if 1 +#define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ +#endif +#if 1 +#define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ +#endif +#if 0 +#define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +#define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +#define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ +#endif +#if 0 +#define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ +#endif + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 + +typedef uint8_t return_type; + +/* Warning: The key length for 256 bit keys overflows a byte + (see comment below) +*/ + +typedef uint8_t length_type; + +typedef struct +{ + uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; + uint8_t rnd; +} aes_context; + +/* The following calls are for a precomputed key schedule + + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). +*/ + +#if defined(AES_ENC_PREKEYED) || defined(AES_DEC_PREKEYED) + +return_type aes_set_key(const uint8_t key[], + length_type keylen, + aes_context ctx[1]); +#endif + +#if defined(AES_ENC_PREKEYED) + +return_type aes_encrypt(const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const aes_context ctx[1]); + +return_type aes_cbc_encrypt(const uint8_t *in, + uint8_t *out, + int32_t n_block, + uint8_t iv[N_BLOCK], + const aes_context ctx[1]); +#endif + +#if defined(AES_DEC_PREKEYED) + +return_type aes_decrypt(const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const aes_context ctx[1]); + +return_type aes_cbc_decrypt(const uint8_t *in, + uint8_t *out, + int32_t n_block, + uint8_t iv[N_BLOCK], + const aes_context ctx[1]); +#endif + +/* The following calls are for 'on the fly' keying. In this case the + encryption and decryption keys are different. + + The encryption subroutines take a key in an array of bytes in + key[L] where L is 16, 24 or 32 bytes for key lengths of 128, + 192, and 256 bits respectively. They then encrypts the input + data, in[] with this key and put the reult in the output array + out[]. In addition, the second key array, o_key[L], is used + to output the key that is needed by the decryption subroutine + to reverse the encryption operation. The two key arrays can + be the same array but in this case the original key will be + overwritten. + + In the same way, the decryption subroutines output keys that + can be used to reverse their effect when used for encryption. + + Only 128 and 256 bit keys are supported in these 'on the fly' + modes. +*/ + +#if defined(AES_ENC_128_OTFK) +void aes_encrypt_128(const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], + uint8_t o_key[N_BLOCK]); +#endif + +#if defined(AES_DEC_128_OTFK) +void aes_decrypt_128(const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], + uint8_t o_key[N_BLOCK]); +#endif + +#if defined(AES_ENC_256_OTFK) +void aes_encrypt_256(const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], + uint8_t o_key[2 * N_BLOCK]); +#endif + +#if defined(AES_DEC_256_OTFK) +void aes_decrypt_256(const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], + uint8_t o_key[2 * N_BLOCK]); +#endif + +#endif diff --git a/User/lib/inc/clist.h b/User/lib/inc/clist.h new file mode 100644 index 0000000..d04158a --- /dev/null +++ b/User/lib/inc/clist.h @@ -0,0 +1,49 @@ +/** + * @file clist.h + * @author xxx + * @date 2023-08-08 23:18:15 + * @brief 简单链表 使用方法 lib\examples\simple_clist.c + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __CLIST_H +#define __CLIST_H +#include "lib.h" +typedef void *cnode; + +/// 链表中一个节点的结构体 +typedef struct CLIST_NODE +{ + cnode data; /// 值 + struct CLIST_NODE *Next; /// 指向下一个结点 +} clist_node_t; + +void clist_init(clist_node_t **ppFirst); ///< 初始化 ,构造一条空的链表 + +void clist_print(clist_node_t *First); ///< 打印链表 + +uint32_t clist_node_count(clist_node_t *First); ///< 获取链表节点数 + +void clist_push_back(clist_node_t **ppFirst, cnode data); ///< 尾部插入 + +void clist_push_front(clist_node_t **ppFirst, cnode data); ///< 头部插入 + +void clist_pop_back(clist_node_t **ppFirst); ///< 尾部删除 + +void clist_pop_front(clist_node_t **ppFirst); ///< 头部删除 + +void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data); ///< 给定结点插入,插入到结点前 + +int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data); ///< 按位置插入 + +void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos); ///< 给定结点删除 + +void clist_remove(clist_node_t **ppFirst, cnode data); ///< 按值删除,只删遇到的第一个 + +void clist_remove_all(clist_node_t **ppFirst, cnode data); ///< 按值删除,删除所有的 + +void clist_destroy(clist_node_t **ppFirst); ///< 销毁 ,需要销毁每一个节点 + +clist_node_t *clist_find(clist_node_t *pFirst, cnode data); ///< 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL + +#endif //__CLIST_H diff --git a/User/lib/inc/cmac.h b/User/lib/inc/cmac.h new file mode 100644 index 0000000..7ff5585 --- /dev/null +++ b/User/lib/inc/cmac.h @@ -0,0 +1,63 @@ +/************************************************************************** +Copyright (C) 2009 Lander Casado, Philippas Tsigas + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +In no event shall the authors or copyright holders be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever resulting from loss of use, data or profits, whether or not +advised of the possibility of damage, and on any theory of liability, +arising out of or in connection with the use or performance of this software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE + +*****************************************************************************/ + +#ifndef _CMAC_H_ +#define _CMAC_H_ + +#include "aes.h" + +#define AES_CMAC_KEY_LENGTH 16 +#define AES_CMAC_DIGEST_LENGTH 16 + +typedef struct _AES_CMAC_CTX +{ + aes_context rijndael; + uint8_t X[16]; + uint8_t M_last[16]; + uint32_t M_n; +} AES_CMAC_CTX; + +// #include + +//__BEGIN_DECLS +void AES_CMAC_Init(AES_CMAC_CTX *ctx); +void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]); +void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len); +// __attribute__((__bounded__(__string__,2,3))); +void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx); +// __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH))); +//__END_DECLS + +#endif /* _CMAC_H_ */ diff --git a/User/lib/inc/cmd.h b/User/lib/inc/cmd.h new file mode 100644 index 0000000..735776a --- /dev/null +++ b/User/lib/inc/cmd.h @@ -0,0 +1,49 @@ +/** + * @file cmd.h + * @author xxx + * @date 2023-06-25 13:07:02 + * @brief 命令解析器 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef _CMD_H_ +#define _CMD_H_ + +#define CMD_HASH 0xb433e5c6 + +#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */ +#define SECTION(x) __attribute__((section(x))) +#define CMD_USED __attribute__((used)) + +#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */ +#define SECTION(x) @x +#define CMD_USED __root +#else +#error "not supported tool chain..." +#endif + +typedef void (*cmd_handler)(void); + +typedef struct cmd +{ + const char *cmd; + const char *cmd_mess; + unsigned int hash; + cmd_handler handler; +} cmd_t; + +/// 注册命令 +#define REGISTER_CMD(cmd, handler, desc) \ + const char _register_##cmd##_cmd[] = #cmd; \ + const char _register_##cmd##_desc[] = #desc; \ + CMD_USED cmd_t _register_##cmd SECTION("CMDS") = \ + { \ + _register_##cmd##_cmd, \ + _register_##cmd##_desc, \ + (unsigned int)CMD_HASH, \ + (cmd_handler)&handler}; + +void cmd_init(void); ///< 初始化命令 +void cmd_parsing(char *str); ///< 命令解析 + +#endif diff --git a/User/lib/inc/data_analysis.h b/User/lib/inc/data_analysis.h new file mode 100644 index 0000000..4ac52fe --- /dev/null +++ b/User/lib/inc/data_analysis.h @@ -0,0 +1,79 @@ +/** + * @file data_analysis.h + * @author xxx + * @date 2023-06-25 13:07:02 + * @brief 处理传输层的数据 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_ +#define COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_ +#include "data_type_def.h" + +typedef enum +{ + DATA_1, + DATA_2, + DATA_MAX, +} DataId_t; // 处理数据模块的个数,请根据实际情况修改 + +#define DATA_NUM (DATA_MAX) + +#define DATA_BUF_RECV_SQQ_LEN 650u +#define DATA_BUF_SEND_SQQ_LEN 0u + +#define DATA_SD_LEN_MAX 2 +#define DATA_LD_LEN_MAX 2 +#define DATA_ED_LEN_MAX 1 + +typedef struct _data_reg_t_ +{ + struct + { + uint8_t len; + uint8_t pos; + uint8_t data[DATA_SD_LEN_MAX]; + BOOL valid; // 是否有效 + } sd; // start delimiter + + struct + { + uint8_t len; + uint8_t pos; // 偏移量,在wait_end_state中根据帧长去掉固定长度来判断是否是结束符 + uint8_t little_endian; + BOOL valid; // 是否有效 + } ld; // length describe + + struct + { + uint16_t len_max; + uint16_t len_min; + } argu; + + struct + { + uint8_t len; + uint8_t data[DATA_ED_LEN_MAX]; + BOOL valid; + } ed; + + BOOL echo_en; + void (*func_ptr)(void); +} data_reg_t; + +typedef void (*data_interupt_cb_t)(uint8_t id, uint8_t ch); ///< 中断回调函数,数据从这里写入 + +extern uint8_t data_read(uint8_t id, void *buffer, uint16_t len); ///< 读取数据 + +extern void data_write(uint8_t id, uint8_t *const string, uint16_t len); ///< TODO 写入数据 + +extern void lock_data(uint8_t data_id); ///< 锁定数据,防止中断写入数据 + +extern void unlock_data(uint8_t data_id); ///< 解锁数据 + +extern data_interupt_cb_t data_fsm_init(uint8_t data_id); ///< 初始化数据状态机 + +extern BOOL data_reg(uint8_t id, data_reg_t reg); ///< 注册数据 + +extern void data_unreg(uint8_t id); ///< 注销数据 +#endif /* COMPONENTS_COMMON_INCLUDE_DATA_ANALYSIS_H_ */ diff --git a/User/lib/inc/data_type_def.h b/User/lib/inc/data_type_def.h new file mode 100644 index 0000000..941a0a3 --- /dev/null +++ b/User/lib/inc/data_type_def.h @@ -0,0 +1,241 @@ +/*** + * @Author: + * @Date: 2023-03-29 13:16:28 + * @LastEditors: xxx + * @LastEditTime: 2023-03-30 00:34:11 + * @Description:数据类型定义 + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __DATA_TYPE_DEF_H_ +#define __DATA_TYPE_DEF_H_ +#include + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#ifndef OK +typedef enum +{ + OK = 0, + FAIL = !OK, +} state_e; +#endif + +#ifndef __IO +#define __IO volatile +#endif + +typedef unsigned char BOOL; /* boolean data */ +typedef unsigned char bool_t; /* boolean data */ + +#if !defined(__stdint_h) && !defined(_GCC_WRAP_STDINT_H) +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned long int uint32_t; +typedef unsigned long long uint64_t; + +typedef signed char int8_t; +typedef signed short int int16_t; +typedef signed long int int32_t; +typedef long long int64_t; +#endif + +typedef float float32; +typedef double float64; + +#ifndef float32_t +typedef float float32_t; +#endif + +#ifndef float64_t +typedef double float64_t; +#endif + +#pragma pack(1) +typedef struct +{ + uint8_t bs[3]; +} uint24_t; +typedef struct +{ + uint8_t bs[5]; +} uint40_t; + +typedef union +{ + float32 f; + int32_t c; +} float32_u; + +#pragma pack() + +typedef uint16_t nwk_id_t; + +/** + * STANDARD BITS + */ +#ifndef BIT0 +#define BIT0 (0x01u) +#define BIT1 (0x02u) +#define BIT2 (0x04u) +#define BIT3 (0x08u) +#define BIT4 (0x10u) +#define BIT5 (0x20u) +#define BIT6 (0x40u) +#define BIT7 (0x80u) +#define BIT8 (0x0100u) +#define BIT9 (0x0200u) +#define BIT10 (0x0400u) +#define BIT11 (0x0800u) +#define BIT12 (0x1000u) +#define BIT13 (0x2000u) +#define BIT14 (0x4000u) +#define BIT15 (0x8000u) +#define BIT16 (0x00010000u) +#define BIT17 (0x00020000u) +#define BIT18 (0x00040000u) +#define BIT19 (0x00080000u) +#define BIT20 (0x00100000u) +#define BIT21 (0x00200000u) +#define BIT22 (0x00400000u) + +#define BIT_SET(x, b) x |= b // 置位 +#define BIT_CLR(x, b) x &= ~b // 清零 +#define BIT_IS_SET(x, b) ((x) & (b)) // 判断某一位是否为1 +#define BIT_IS_CLR(x, b) (!((x) & (b))) // 判断某一位是否为0 + +#endif + +#ifndef BF +/** + * @brief 从一个字节中提取指定位的值 + * @return {*} + * @note + *> uint8_t num = 0x12; 二进制表示为00010010

+ *> uint8_t bit = 2; 提取第2位(从0开始计数)

+ *> uint8_t width = 1; 提取1位

+ *> uint8_t result = BF(num, bit, width); 结果为1

+ */ +#define BF(x, b, s) (((x) & (b)) >> (s)) +#endif + +#ifndef MIN +/** + * @brief + * @return {*} + * @note + *> int num1 = 10;

+ *> int num2 = 20;

+ *> int result = MIN(num1, num2); // 结果为10

+ */ +#define MIN(n, m) (((n) < (m)) ? (n) : (m)) +#endif + +#ifndef MAX +/** + * @brief + * @return {*} + * @note + *> int num1 = 10;

+ *> int num2 = 20;

+ *> int result = MAX(num1, num2); // 结果为20

+ */ +#define MAX(n, m) (((n) < (m)) ? (m) : (n)) +#endif + +#ifndef ABS +/** + * @brief + * @return {*} + * @note + *> int num = -10; + *> int result = ABS(num); // 结果为10 + */ +#define ABS(n) (((n) < 0) ? -(n) : (n)) +#endif + +#ifndef RANGE +#define RANGE(x, a, b) (MIN(MAX(x, a), b)) +#endif + +#define ARRAY_LEN(arr) (sizeof(arr)) / (sizeof(arr[0])) + +#define HI_UINT16(a) (((uint16_t)(a) >> 8) & 0xFF) +#define LO_UINT16(a) ((uint16_t)(a) & 0xFF) + +#define HI_1_UINT32(a) (((uint32_t)(a) >> 24) & 0xFF) +#define HI_2_UINT32(a) (((uint32_t)(a) >> 16) & 0xFF) +#define HI_3_UINT32(a) (((uint32_t)(a) >> 8) & 0xFF) +#define HI_4_UINT32(a) ((uint32_t)(a) & 0xFF) + +#define LO_1_UINT8(a) (uint8_t)((a) & 0xFF) +#define LO_2_UINT8(a) (uint8_t)(((a) & 0xFF00) >> 8) +#define LO_3_UINT8(a) (uint8_t)(((a) & 0xFF0000) >> 16) +#define LO_4_UINT8(a) (uint8_t)(((a) & 0xFF000000) >> 24) + +// uint32小端转大端 +#define S2B_UINT32(a) \ + (((uint32_t)(a) & 0xFF000000) >> 24) + (((uint32_t)(a) & 0x00FF0000) >> 8) + (((uint32_t)(a) & 0x0000FF00) << 8) + (((uint32_t)(a) & 0x000000FF) << 24) + +// uint32大端转小端 +#define B2S_UINT32(a) S2B_UINT32(a) + +// uint16小端转大端 +#define S2B_UINT16(a) ((((uint16_t)(a) & 0xFF00) >> 8) + (((uint16_t)(a) & 0x00FF) << 8)) + +// uint16大端转小端 +#define B2S_UINT16(a) S2B_UINT16(a) + +#define BUILD_UINT16(loByte, hiByte) \ + ((uint16_t)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8))) + +// float32小端转大端 +static inline float32 S2B_FLOAT32(float fv) +{ + float32_u _f; + _f.f = fv; + _f.c = S2B_UINT32(_f.c); + return _f.f; +} + +// float32大端转小端 +#define B2S_FLOAT32(a) S2B_FLOAT32(a) + +// 反序数组 +#define REVERSE_ARRAY(arr, len) \ + do \ + { \ + uint8_t _tmp; \ + uint16_t _i; \ + for (_i = 0; _i < len / 2; _i++) \ + { \ + _tmp = arr[_i]; \ + arr[_i] = arr[len - _i - 1]; \ + arr[len - _i - 1] = _tmp; \ + } \ + } while (0); + +// 比较2个数组是否相等 +#define IsEqual(arr1, arr2, n) ({ \ + int _equal = 1; \ + for (int _i = 0; _i < n; _i++) \ + { \ + if (arr1[_i] != arr2[_i]) \ + { \ + _equal = 0; \ + break; \ + } \ + } \ + _equal; \ +}) + +// ASSIC码转换为数字 +#define ASCII_TO_NUM(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : (c) - 'A' + 10) + +// 数字转换为ASSIC码 +#define NUM_TO_ASCII(x) ((x) < 10 ? (x) + '0' : (x)-10 + 'A') +#endif /* __DATA_TYPE_DEF_H_ */ diff --git a/User/lib/inc/debug.h b/User/lib/inc/debug.h new file mode 100644 index 0000000..e1745f0 --- /dev/null +++ b/User/lib/inc/debug.h @@ -0,0 +1,21 @@ +/*** + * @Author: + * @Date: 2023-04-04 08:13:11 + * @LastEditors: xxx + * @LastEditTime: 2023-04-04 13:21:46 + * @Description: + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#ifndef __DEBUG_H +#define __DEBUG_H +#include "lib.h" + +/*形参*/ +#define _DBG_LINE_ , uint16_t line +/*实参*/ +#define __DBG_LINE , __LINE__ + +extern BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_); + +#endif //__DEBUG_H diff --git a/User/lib/inc/filter.h b/User/lib/inc/filter.h new file mode 100644 index 0000000..54d0a6c --- /dev/null +++ b/User/lib/inc/filter.h @@ -0,0 +1,56 @@ +/** + * @file filter.h + * @author xxx + * @date 2023-08-08 22:59:46 + * @brief + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __FILTER_H__ +#define __FILTER_H__ +#include "lib.h" + +typedef struct +{ + float32 Last_P; // 上次估算协方差 不可以为0 ! ! ! ! ! + float32 Now_P; // 当前估算协方差 + float32 out; // 卡尔曼滤波器输出 + float32 Kg; // 卡尔曼增益 + float32 Q; // 过程噪声协方差 + float32 R; // 观测噪声协方差 + + uint8_t filter_count; + uint8_t default_filter_count; + float32 filter_limit; + BOOL change; +} kalman_t; // 卡尔曼滤波器 + +typedef struct +{ + BOOL fisrt_flag; // 第一次标志位 + float32 alpha; // 滤波系数 0~1 + float32 last_value; // 上次滤波结果 +} lpf_t; // 一阶低通滤波器 + +typedef struct +{ + uint16_t size; // 滑动窗口大小 + float32 *window; // 滑动窗口 + volatile float32 sum; // 滑动窗口和 + volatile float32 out; // 滤波结果 + uint16_t index; // 滑动窗口索引 +} lpf_window_t; // 滑动窗口滤波器 + +void kalman_init(kalman_t *cfg); +void kalman_reset(kalman_t *cfg); +float32 kalman_update(kalman_t *cfg, float32 input); + +void lpf_init(lpf_t *cfg); +float32 lpf_update(lpf_t *cfg, float32 input); +void lpf_reset(lpf_t *cfg); + +lpf_window_t *lpf_window_init(uint16_t size); +void lpf_window_dinit(lpf_window_t *cfg); +float32 lpf_window_update(lpf_window_t *cfg, float32 input); +void lpf_window_reset(lpf_window_t *cfg); +#endif // __FILTER_H__ diff --git a/User/lib/inc/fsm.h b/User/lib/inc/fsm.h new file mode 100644 index 0000000..4bdb7b6 --- /dev/null +++ b/User/lib/inc/fsm.h @@ -0,0 +1,307 @@ +#ifndef __FSM_H__ +#define __FSM_H__ +#include +/* ----------------------- Defines ------------------------------------------*/ +// 用于快速识别出 STATE与STEP +#define FSM_STATE(name) state_##name +#define FSM_FUNCT(name) funct_##name + +// 数据类型定义区 +typedef signed char state; +typedef long long step_ret; +typedef void *AS_STEP_RETVAL; + +/*! + * @brief 状态机过程实现原型函数 + * 设计状态机时需要按照这个模式写 + * + * @param[in] void* 你所需要的任何参数 + * + * @return 返回值 代表下一个状态 + */ +typedef void *(*Procedure)(void *); + +typedef struct +{ + state ds; // 默认状态 + state cs; // 当前状态 + state ns; // 下个状态 +} SM_STATE; + +// 状态机 属性 定义 +typedef struct +{ + // 状态管理 + SM_STATE st; + + // 状态机跳转表 + Procedure *procedures; + + // 状态机数据区域 + void *data; + + // 错误处理(用于存放 状态 执行 的结果) + step_ret ret_ptr; // 状态 执行结果 + void *err_ptr; + state err_flag; +} FSM; + +/* ----------------------- Start function declaration -----------------------------*/ + +/*! + * @brief 设置状态机的错误容器 + * + * @param[in] fsm 状态机实例 + * + * @param[in] err_var 容器 + * + * @return 是/否 + */ +static inline void set_err_var(FSM *fsm, void *err_var) +{ + if (!fsm) + return; + fsm->err_ptr = err_var; +} + +/*! + * @brief 获取错误值容器(用于读取其中的内容) + * + * @param[in] fsm 状态机实例 + * + * @return 是/否 + */ +static inline void *get_err_var(FSM *fsm) +{ + return fsm->err_ptr; +} + +/*! + * @brief 获取状态机 在 步进中是否遇到了错误。 + * + * @param[in] fsm 状态机实例 + * + * @return 是/否 + */ +static inline state is_fsm_error(FSM *fsm) +{ + return fsm->err_flag; +} + +/*! + * @brief 置 状态机 错误位 + * + * @param[in] fsm 状态机实例 + * + * @return 是/否 + */ +static inline state set_fsm_error_flag(FSM *fsm) +{ + if (!fsm) + return -1; + fsm->err_flag = 1; + return 0; +} + +/*! + * @brief 置 状态机 错误位 + * + * @param[in] fsm 状态机实例 + * + * @return 是/否 + */ +static inline state clr_fsm_error_flag(FSM *fsm) +{ + if (!fsm) + return -1; + fsm->err_flag = 0; + return 0; +} + +/*! + * @brief 为状态机添加 过程方法 序列 + * + * @param[in] fsm 状态机实例 + * + * @param[in] procedures 状态机的所有过程方法 + * + */ +static inline void set_procedures(FSM *fsm, Procedure *procedures) +{ + if (fsm) + { + fsm->procedures = procedures; + fsm->st.cs = -1; // 执行run之前,当前状态是未定的 + } +} + +/*! + * @brief 配置状态机的数据域 + * + * @param[in] fsm 状态机实例 + * + * @param[in] data 状态机需要的数据域 + * + */ +static inline void set_data_entry(FSM *fsm, void *data) +{ + if (fsm) + fsm->data = data; +} + +/*! + * @brief 配置状态机的数据域 + * + * @param[in] fsm 状态机实例 + * + * @return 返回 状态机 数据域 + * + */ +static inline void *get_data_entry(FSM *fsm) +{ + return fsm->data; +} + +/*! + * @brief 让 状态机 步进一次 + * + * @param[in] fsm 状态机实例 + * + * @return 非负数 :代表 所成功执行的状态 + * -1 : 失败 + */ +static inline state run_state_machine_once(FSM *fsm) +{ + if (!fsm) + return -1; + + // 切换到新状态 + fsm->st.cs = fsm->st.ns; + + // 跳转到下一个状态(状态 执行 结果 保存在 ret_ptr 中 ) + fsm->ret_ptr = (step_ret)fsm->procedures[fsm->st.cs](fsm); + + return fsm->st.cs; +} + +/*! + * @brief 获取步进执行结果 + * + * @param[in] fsm 状态机实例 + * + * @return 是/否 + */ +static inline step_ret *get_step_retval(FSM *fsm) +{ + return &fsm->ret_ptr; +} + +/*! + * @brief 获取状态机的当前状态 + * + * @param[in] fsm 状态机实例 + * + * @return 当前状态 + */ +static inline state get_curr_state(FSM *fsm) +{ + return fsm->st.cs; +} + +/*! + * @brief 设置状态机默认状态 + * + * @param[in] fsm 状态机实例 + * + * @param[in] st 状态值 + * + */ +static inline void set_default_state(FSM *fsm, state st) +{ + if (!fsm) + return; + fsm->st.ds = st; + fsm->st.ns = st; +} + +/*! + * @brief 设置状态机的下次状态 + * + * @param[in] fsm 状态机实例 + * + * @param[in] st 状态值 + * + */ +static inline void set_next_state(FSM *fsm, state st) +{ + if (fsm) + fsm->st.ns = st; +} + +/*! + * @brief 获取状态机的下次状态 + * + * @param[in] fsm 状态机实例 + * + * @return 下一个状态 + */ +static inline state get_next_state(FSM *fsm) +{ + return fsm->st.ns; +} + +/*! + * @brief 将状态机设为默认状态 + * + * @param[in] fsm 状态机实例 + * + */ +static inline void init_state_machine(FSM *p) +{ + set_next_state(p, p->st.ds); + p->st.cs = -1; // 执行run之前,当前状态是未定的 +} + +/*! + * @brief 将状态机设为默认状态,同时清除错误状态 + * + * @param[in] fsm 状态机实例 + * + */ +static inline void reset_state_machine(FSM *p) +{ + if (!p) + return; + clr_fsm_error_flag(p); + init_state_machine(p); +} + +/*! + * @brief 判断状态机是否在某个状态 + * + * @param[in] fsm 状态机实例 + * + * @param[in] st 状态值 + * + * @return 是/否 + */ +static inline state is_curr_state(FSM *fsm, state st) +{ + return fsm->st.cs == st; +} + +/*! + * @brief 判断状态机是否即将进行某个状态 + * + * @param[in] fsm 状态机实例 + * + * @param[in] st 状态值 + * + * @return 是/否 + */ +static inline state is_next_state(FSM *fsm, state st) +{ + return fsm->st.ns == st; +} + +#endif // __FSM_H__ diff --git a/User/lib/inc/lib.h b/User/lib/inc/lib.h new file mode 100644 index 0000000..b04099d --- /dev/null +++ b/User/lib/inc/lib.h @@ -0,0 +1,77 @@ +/*** + * @Author: + * @Date: 2023-04-04 08:13:11 + * @LastEditors: xxx + * @LastEditTime: 2023-04-04 10:13:21 + * @Description: + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __LIB_H +#define __LIB_H +#include +#include "data_type_def.h" +#include "malloc.h" +#include "data_analysis.h" +#include "osel_arch.h" +#include "debug.h" +#include "sqqueue.h" +#include "clist.h" + +#define INTERNAL_EXTERN extern + +#ifndef STM32 +#include "log.h" +#else +#define LOG_PRINT(fmt, ...) \ + do \ + { \ + } while (0); +#define LOG_ERR(fmt, ...) \ + do \ + { \ + } while (0); +#define LOG_HEX(data, len) \ + do \ + { \ + } while (0); +#endif + +typedef struct +{ + uint16_t year; + uint8_t month; + uint8_t day; +} rtc_date_t; + +typedef struct +{ + uint8_t hour; + uint8_t minute; + uint8_t second; +} rtc_time_t; + +extern uint32_t cpu_encrypt(void); // CPU加密 +extern BOOL cpu_judge_encrypt(uint32_t cupid_encrypt); // CPU判断加密 +extern void version_split(uint8_t *version, uint8_t *hi, uint8_t *lo); // 版本号1.0拆解成1和0 +extern void reverse(uint8_t *buf, uint16_t len); // 反序数组 +extern BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val); // 判断val是否在数组arr中 +extern BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value); // 判断数组中的值是否都相等 +extern uint16_t crc16_compute(const uint8_t *const data, uint16_t length); // CRC16校验 +extern uint32_t crc32_compute(const uint8_t *const data, uint16_t length); // CRC32校验 +extern uint8_t xor_compute(const uint8_t *const data, uint16_t length); // 异或校验 +extern uint8_t get_bit_num(uint8_t bit); // 获取bit位的值 +extern BOOL is_bit_set(int x, int k); // 判断x的第k位是否为1 +extern uint8_t isLeap(uint16_t year); // 检查是否是闰年 +extern uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几天 +extern uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day); // 计算一年中的第几周 +extern uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day); // 获取今天星期几 +extern uint8_t hex_format_dec(uint8_t hex); // 十六进制转十进制 +extern uint8_t dec_format_hex(uint8_t dec); // 十进制转十六进制 +extern void quicksort(uint16_t arr[], int low, int high); // 快速排序 + +extern uint32_t time2stamp(rtc_date_t date, rtc_time_t time); // 北京时间转时间戳 +extern void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time); // 时间戳转北京时间 + +#endif //__LIB_H diff --git a/User/lib/inc/log.h b/User/lib/inc/log.h new file mode 100644 index 0000000..802ba9f --- /dev/null +++ b/User/lib/inc/log.h @@ -0,0 +1,45 @@ +/*** + * @Author: + * @Date: 2023-03-20 19:27:47 + * @LastEditors: xxx + * @LastEditTime: 2023-03-30 00:34:41 + * @Description:日志打印模块PC端调试使用 + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __LOG_H_ +#define __LOG_H_ +#include +#include + +#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__) + +/*调试日志宏定义*/ + +#define LOG_PRINT(fmt, ...) \ + do \ + { \ + printf("[DEBUG:%s][%s:%d] " fmt "\n", __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + } while (0); + +/*错误日志打印(在日志打印模块还未启动时使用)*/ +#define LOG_ERR(fmt, ...) \ + do \ + { \ + printf("[ERROR:%s][%s:%d] " fmt "\n", __FILENAME__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + } while (0); + +// 打印十六进制字符串 +#define LOG_HEX(data, len) \ + do \ + { \ + printf("[DEBUG:%s][%s:%d] ", __FILENAME__, __FUNCTION__, __LINE__); \ + for (int i = 0; i < len; i++) \ + { \ + printf("%02x ", data[i]); \ + } \ + printf("\n"); \ + } while (0); + +#endif //__LOG_H_ diff --git a/User/lib/inc/malloc.h b/User/lib/inc/malloc.h new file mode 100644 index 0000000..c408863 --- /dev/null +++ b/User/lib/inc/malloc.h @@ -0,0 +1,45 @@ +#ifndef _MOLLOC_H +#define _MOLLOC_H + +#include "../inc/data_type_def.h" + +#ifndef NULL +#define NULL 0 +#endif + +// 定义两个内存池 +#define SRAMIN 0 // 内部内存池 +#define SRAMEX 1 // 外部内存池(精英STM32开发板不支持外部内存) +// 我们又多少个SRAM可管理 +#define SRAMBANK 2 // 定义支持的SRAM块数. 精英版实际上只支持1个内存区域,即内部内存. + +// mem1内存参数设定.mem1完全处于内部SRAM里面.(设置内部SARM的内存池和内存表的参数) +#define MEM1_BLOCK_SIZE 32 // 一个内存块大小为32字节 +#define MEM1_MAX_SIZE 26 * 1024 // 最大管理内存 1K (我们这个内存管理系统的内部SRAM可控制的内存大小) +#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE / MEM1_BLOCK_SIZE // 内存表大小(有多少块内存块) + +// mem2内存参数设定.mem2的内存池处于外部SRAM里面 +#define MEM2_BLOCK_SIZE 32 // 一个内存块大小为32字节 +#define MEM2_MAX_SIZE 1 * 1024 // 因为精英版没有外扩内存,故这里设置一个最小值 +#define MEM2_ALLOC_TABLE_SIZE MEM2_MAX_SIZE / MEM2_BLOCK_SIZE // 内存表大小 + +// 内存管理控制器结构体 +// 注意:内存管理由内存池和内存列表组成 +// SRAMBANK:SARM块数,一般有内部SRAM和外部SRAM、CCM +struct _m_mallco_dev +{ + void (*init)(uint8_t); // 初始化 + uint8_t (*perused)(uint8_t); // 内存使用率 + uint8_t *membase[SRAMBANK]; // 内存池 管理SRAMBANK个区域的内存 + uint16_t *memmap[SRAMBANK]; // 内存管理状态表 + uint8_t memrdy[SRAMBANK]; // 内存管理是否就绪 +}; + +void my_mem_init(uint8_t memx); +uint8_t my_mem_perused(uint8_t memx); + +void *mymalloc(uint8_t memx, uint32_t size); +void myfree(uint8_t memx, void *ptr); +void *myrealloc(uint8_t memx, void *ptr, uint32_t size); + +#endif diff --git a/User/lib/inc/mlist.h b/User/lib/inc/mlist.h new file mode 100644 index 0000000..ebc043f --- /dev/null +++ b/User/lib/inc/mlist.h @@ -0,0 +1,268 @@ +/*** + * @Author: + * @Date: 2023-04-04 08:39:32 + * @LastEditors: xxx + * @LastEditTime: 2023-04-04 08:46:20 + * @Description:双向链表操作接口 该双向链表的操作,请参照Linux内核 (include/linux/list.h) + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __LIST_H +#define __LIST_H +#include +#include "data_type_def.h" +typedef struct list_head +{ + struct list_head *next; + struct list_head *prev; +} list_head_t; + +/** + * 获得链表元素所在实体的地址, 该实体在链表中保存 + * + * @param ptr: 链表的入口指针 + * @param type: 结构类型 + * @param member: 元素结构中链表变量的名字 + * + * @return 指向该元素所在实体的指针 + */ +#define list_entry_addr_find(ptr, type, member) \ + ((type *)((char *)(ptr) - (char *)(&((type *)NULL)->member))) + +/** + * 移除并返回链表中首元素所在的实体,该实体在链表中不保存 + * + * @param head: 链表的入口指针 + * @param type: 结构类型 + * @param member: 指向该链表的第一个元素的指针 + * + * @return 表首元素所在实体的指针,链表为空则返回空指针 + */ +#define list_entry_decap(head, type, member) \ + ( \ + (list_empty(head)) ? (type *)NULL \ + : (list_entry_addr_find(list_next_elem_get(head), type, member))) + +#define list_entry_get_head(head, type, member) \ + ((list_empty(head)) ? (type *)NULL : (list_entry_addr_find((head)->next, type, member))) +/** + * 移除并返回链表尾部所在实体,该实体在链表中不保存 + * + * @param head: 链表入口指针 + * @param type: 链表所在结构体的名称 + * @param member: 结构体中,链表变量的名称 + * + * @return 表尾部所在实体指针,链表为空则返回空指针 + */ +#define list_entry_curtail(head, type, member) \ + ((list_empty(head)) ? (type *)NULL \ + : (list_entry_addr_find(list_curtail(head), type, member))) + +/** + * 正向遍历链表,在该遍历中不能对链表做删除操作 -- list_for_each + * + * @param pos: 链表元素计数器 + * @param head: 链表的入口指针 + */ +#define list_for_each_forwards(pos, head) \ + for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next) + +/** + * 反向遍历链表,在该遍历中不能对链表做删除操作 + * + * @param pos: 链表元素计数器 + * @param head: 链表的入口指针 + */ +#define list_for_each_backwards(pos, head) \ + for ((pos) = (head)->prev; (pos) != (head); (pos) = (pos)->prev) + +/** + * 链表遍历,支持删除操作 + * + * @param pos: 链表元素计数器 + * @param n: 临时链表元素 + * @param head: 链表入口指针 + */ +#define list_for_each_safe(pos, n, head) \ + for ((pos) = (head)->next, n = (pos)->next; (pos) != (head); \ + (pos) = n, n = (pos)->next) + +/** + * 遍历链表所在实体,不可删除实体 + * + * @param pos: 链表元素计数器 + * @param head: 链表入口指针 + * @param type: 链表所在结构体的名称 + * @param member: 结构体中,链表变量的名称 + */ +#define list_entry_for_each(pos, head, type, member) \ + for ((pos) = list_entry_addr_find((head)->next, type, member); \ + &(pos)->member != (head); \ + (pos) = list_entry_addr_find((pos)->member.next, type, member)) + +/** + * 遍历链表所在实体, 支持删除操作 + * + * @param pos: 链表元素计数器 + * @param n: 临时链表元素 + * @param head: 链表入口指针 + * @param type: 链表所在结构体的名称 + * @param member: 结构体中,链表变量的名称 + */ +#define list_entry_for_each_safe(pos, n, head, type, member) \ + for ((pos) = list_entry_addr_find((head)->next, type, member), \ + n = list_entry_addr_find((pos)->member.next, type, member); \ + &(pos)->member != (head); \ + (pos) = n, n = list_entry_addr_find(n->member.next, type, member)) + +/** + * 计算链表中元素的个数 + */ +#define list_count(head, count) \ + do \ + { \ + count = 0; \ + for (list_head_t *pos = (head)->next; pos != (head); pos = pos->next) \ + { \ + count++; \ + } \ + } while (0) + +/** + * 将实体按顺序插入到链表中合适的地方,顺序由函数funcCompare来决定 -- list_sorted_add + * + * @param new_entry: 所要插入的实体 + * @param head: 链表头 + * @param type: 链表所在结构体的名称 + * @param member: 结构体中,链表变量的名称 + * @param func_compare: 顺序比较函数,声明:bool func_compare(Node* A, Node* B) + * 如果 A < B, 返回 true, 否则返回 false + * @param pos: 链表元素计数器 + */ +#define list_entry_sorted_add(new_entry, head, type, member, func_compare, pos) \ + do \ + { \ + type *entry_a = NULL; \ + type *entry_b = NULL; \ + for ((pos) = (head)->next; (pos) != (head); (pos) = (pos)->next) \ + { \ + entry_a = list_entry_addr_find((new_entry), type, member); \ + entry_b = list_entry_addr_find((pos), type, member); \ + if (func_compare(entry_a, entry_b)) \ + { \ + break; \ + } \ + } \ + if ((pos) != (head)) \ + { \ + list_insert_forwards((new_entry), (pos)); \ + } \ + else \ + { \ + list_add_to_tail((new_entry), (head)); \ + } \ + } while (__LINE__ == -1) + +/** + * 链表头初始化 + * + * @param ptr: 需要被初始化的链表头指针 + */ +void list_init(list_head_t *const ptr); + +/** + * 在指定位置之前插入新的元素 + * + * @param new_entry: 需要放入链表中的新元素 + * @param pos: 链表中放入新元素的位置指针 + */ +void list_insert_forwards(list_head_t *const new_entry, list_head_t *const pos); + +/** + * 在指定位置之后插入新的元素 + * + * @param new_entry: 需要放入链表中的新元素 + * @param pos: 链表中放入新元素的位置指针 + */ +void list_insert_backwards(list_head_t *const new_entry, list_head_t *const pos); + +/** + * 在链表尾部之后插入新的元素 -- list_append + * + * @param new_entry: 需要放入链表尾部的新元素 + * @param list: 链表头指针 + */ +void list_add_to_tail(list_head_t *const new_entry, list_head_t *const list); + +/** + * 在链表头部之后插入新的元素 + * + * @param new_entry: 需要放入链表尾部的新元素 + * @param list: 链表头指针 + */ +void list_add_to_head(list_head_t *const new_entry, list_head_t *const list); + +/** + * 将指定元素从链表中删除 + * + * @param elem: 需要删除的链表元素 + */ +void list_del(list_head_t *const elem); + +/** + * 将链表的尾元素删除并返回 + * + * @param head: 链表指针 + * + * @return 链表尾元素 + */ +list_head_t *list_curtail(const list_head_t *const head); + +/** + * 判断链表是否为空 + * + * @param head: 链表头指针 + * + * @return 为空时返回TRUE,否则为FALSE + */ +bool list_empty(const list_head_t *const head); + +/** + * 获取链表中第一个元素的地址 -- list_get_head + * + * @param head: 链表头指针 + * + * @return 首元素的地址 + */ +list_head_t *list_first_elem_look(const list_head_t *const head); + +/** + * 取出给定位置的下一个元素 + * + * @param pos: 链表元素地址 + * + * @return 下一个链表元素地址 + */ +list_head_t *list_next_elem_get(const list_head_t *const pos); + +/** + * 将一个元素从一个链表中移除,然后再插入另外一个链表中的头部 + * + * @param elem: 被移除的链表元素 + * @param head: 新链表头 + */ +void list_move_to_another_head(list_head_t *const elem, list_head_t *const head); + +/** + * 将一个元素从一个链表中移除,然后再放入另外一个链表中的尾部 + * + * @param elem: 被移除的链表元素 + * @param head: 新链表头 + */ +void list_move_to_another_tail(list_head_t *const elem, list_head_t *const head); + +#endif +/** + * @} + */ diff --git a/User/lib/inc/osel_arch.h b/User/lib/inc/osel_arch.h new file mode 100644 index 0000000..9860e8c --- /dev/null +++ b/User/lib/inc/osel_arch.h @@ -0,0 +1,181 @@ +/*** + * @Author: + * @Date: 2023-04-04 08:13:11 + * @LastEditors: xxx + * @LastEditTime: 2023-04-04 08:16:58 + * @Description: + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __OSEL_ARCH_H__ +#define __OSEL_ARCH_H__ + +#include "lib.h" +#define hal_int_state_t char +#ifdef STM32 +#include "stm32l4xx.h" +#define HAL_ENTER_CRITICAL(__HANDLE__) \ + do \ + { \ + if ((__HANDLE__)->Lock == HAL_LOCKED) \ + { \ + return HAL_BUSY; \ + } \ + else \ + { \ + (__HANDLE__)->Lock = HAL_LOCKED; \ + } \ + } while (0U) + +#define HAL_EXIT_CRITICAL(__HANDLE__) \ + do \ + { \ + (__HANDLE__)->Lock = HAL_UNLOCKED; \ + } while (0U) +#else +#define HAL_ENTER_CRITICAL(__HANDLE__) + +#define HAL_EXIT_CRITICAL(__HANDLE__) + +#endif + +#define osel_memset _memset +#define osel_memcmp _memcmp +#define osel_memcpy _memcpyL +#define osel_memcpyr _memcpyR +#define osel_reverse _reverse +#define osel_mem_alloc _malloc +#define osel_mem_free _free +#define osel_mem_alloc2 _malloc2 +#define osel_mem_free2 _free2 +#define osel_mstrlen _mstrlen + +static inline void *_malloc(uint32_t size) +{ + return mymalloc(SRAMIN, size); +} + +static inline void _free(void *ptr) +{ + myfree(SRAMIN, ptr); +} + +static inline void *_malloc2(uint32_t size) +{ + return mymalloc(SRAMEX, size); +} + +static inline void _free2(void *ptr) +{ + myfree(SRAMEX, ptr); +} + +/** + * @brief Fills a block of memory with a given value. + * + * @param dst The destination block of memory. + * @param value The value to fill the memory with. + * @param size The size of the memory block, in bytes. + */ +static inline void _memset(uint8_t *dst, uint8_t value, uint16_t size) +{ + while (size--) + { + *dst++ = value; + } +} + +/** + * @brief Compares two blocks of memory for equality. + * + * @param[in] dst The first block of memory to compare. + * @param[in] src The second block of memory to compare. + * @param[in] size The number of bytes to compare. + * + * @return 0 if the blocks of memory are equal, -1 otherwise. + */ +static inline int8_t _memcmp(const uint8_t *dst, const uint8_t *src, uint16_t size) +{ + while (size--) + { + if (*dst++ != *src++) + { + return -1; + } + } + return 0; +} + +/** + * @brief Copies data from a source buffer to a destination buffer in a forward direction. + * + * @param dst The destination buffer. + * @param src The source buffer. + * @param size The number of bytes to copy. + */ +static inline void _memcpyL(uint8_t *dst, const uint8_t *src, uint16_t size) +{ + while (size--) + { + *dst++ = *src++; + } +} + +/** + * @brief Copies data from a source buffer to a destination buffer in reverse order. + * + * @param dst The destination buffer. + * @param src The source buffer. + * @param size The number of bytes to copy. + */ +static inline void _memcpyR(uint8_t *dst, const uint8_t *src, uint16_t size) +{ + // dst is a pointer to the last byte of the destination buffer + // src is a pointer to the first byte of the source buffer + // size is the number of bytes to copy + + // decrement the destination pointer by the size, since we want to write to the last byte of the buffer + dst = dst + (size - 1); + + // loop through each byte in the buffer, copying from the source to the destination in reverse order + while (size--) + { + // write the next byte from the source to the destination + *dst-- = *src++; + } +} + +/** + * @brief Reverses the order of bytes in a buffer + * + * @param buf The buffer to reverse + * @param len The length of the buffer, in bytes + */ +static inline void _reverse(uint8_t *buf, uint16_t len) +{ + uint8_t temp = 0; + uint16_t i; + for (i = 0; i < len / 2; i++) + { + temp = buf[i]; + buf[i] = buf[len - i - 1]; + buf[len - i - 1] = temp; + } +} +/** + * @brief Returns the length of a null-terminated string + * + * @param s The string to measure + * @return The length of the string, not including the null terminator + */ +static inline unsigned int _mstrlen(const unsigned char *s) +{ + const unsigned char *ss = s; + while (*ss) + ss++; + + return ss - s; +} + +#endif // __OSEL_ARCH_H__ diff --git a/User/lib/inc/pbuf.h b/User/lib/inc/pbuf.h new file mode 100644 index 0000000..ee3a6ce --- /dev/null +++ b/User/lib/inc/pbuf.h @@ -0,0 +1,169 @@ +/*** + * @Author: + * @Date: 2023-04-04 10:06:40 + * @LastEditors: xxx + * @LastEditTime: 2023-04-04 13:21:27 + * @Description: + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef COMPONENTS_COMMON_INCLUDE_PBUF_H_ +#define COMPONENTS_COMMON_INCLUDE_PBUF_H_ +#include "../inc/data_type_def.h" +#include "../inc/mlist.h" +#include "../inc/malloc.h" + +#define PBUF_DBG_EN (1u) +#define PBUF_TYPE_MAX_NUM (3u) + +#define PBUF_NUM_MAX (10u) + +// 如果size>254,并使用data_analysis接收数据,需要修改data_analysis.c中的DATA_BUF_RECV_SQQ_LEN +#define SMALL_PBUF_BUFFER_SIZE (32) +#define MEDIUM_PBUF_BUFFER_SIZE (32 * 2) +#define LARGE_PBUF_BUFFER_SIZE (32 * 4) + +#define SMALL_PBUF_NUM (4u) // 各种PBUF最大个数 +#define MEDIUM_PBUF_NUM (4u) +#define LARGE_PBUF_NUM (4u) + +#if PBUF_DBG_EN > 0 + +/*形参*/ +#define _PLINE1_ , uint16_t line +#define _PLINE2_ , uint16_t line +/*实参*/ +#define __PLINE1 , __LINE__ +#define __PLINE2 , __LINE__ + +#else + +#define _PLINE1_ +#define _PLINE2_ +#define __PLINE1 +#define __PLINE2 + +#endif + +enum _PBUF_TYPE +{ + SMALL_PBUF, + MEDIUM_PBUF, + LARGE_PBUF, + PBUF_TYPE_INVALID +}; + +typedef struct __send_times_t +{ + uint8_t app_send_times; + uint8_t mac_send_times; +} send_times_t; + +typedef struct +{ + int8_t rssi_dbm; + uint8_t seq; + + nwk_id_t src_id; // 接收到数据帧时,为同步模块提供同步对象信息; + nwk_id_t dst_id; // 填写帧的目的节点网络地址 + + uint8_t send_mode : 2, + is_ack : 1, + need_ack : 1, + crc_ok : 1, + is_pending : 1, + debug_info : 1, + reserved : 1; + + send_times_t already_send_times; +} pkt_attri_t; + +typedef struct +{ + struct list_head list; + uint8_t *data_p; // 指向数据区 + uint8_t *head; // 指向数据区的第一个字节 + uint8_t *end; // 指向数据区的最后一个字节 + uint16_t data_len; // 该pbuf的实际数据长度 + pkt_attri_t attri; + bool used; +#if PBUF_DBG_EN > 0 + uint16_t alloc_line; + uint16_t free_line; +#endif +} pbuf_t; + +/** + * pbuf_initz: 为pbuf申请一块内存区域,需要配置各种pbuf的大小和数量等 + */ +void pbuf_initz(void); + +/** + * 申请一个pbuf,用来存放用户数据 + * + * @param size: 用户的数据长度 + * @param _PLINE1_: pbuf_allocz()位置的行号,调用时传入实参形式__PLINE1 + * + * @return: 申请成功则返回pbuf的指针,失败则进入断言 + */ +extern pbuf_t *pbuf_allocz(uint16_t size _PLINE1_); + +/** + * 释放已经使用完的pbuf + * + * @param pbuf: 需要操作的pbuf的指针的指针 + * @param _PLINE2_: 调用pbuf_freez()位置的行号,调用时传入实参形式__PLINE2 + * + * @return: 无 + */ +void pbuf_freez(pbuf_t **const pbuf _PLINE2_); + +/** + * 向pbuf->end方向移动pbuf->data_p指针,移动距离为len + * + * @param pbuf: 需要操作的pbuf的指针 + * @param len: data_p需要移动的距离 + * + * @return: 成功则返回data_p指针,失败返回NULL + */ +extern uint8_t *pbuf_skip_datap_forward(pbuf_t *const pbuf, + uint8_t len); + +/** + * 向pbuf->head方向移动pbuf->data_p指针,移动距离为len + * + * @param pbuf: 需要操作的pbuf的指针 + * @param len: data_p需要移动的距离 + * + * @return: 成功则返回data_p指针,失败返回NULL + */ +extern uint8_t *pbuf_skip_datap_backward(pbuf_t *const pbuf, + uint8_t len); + +/** + * 向pbuf的数据区拷贝数据,并移动data_p指针,改变data_len + * + * @param pbuf: 目的地址pbuf的指针(从pbuf->data_p开始拷贝) + * @param src: 源地址的指针 + * @param len: 需要拷贝的数据长度 + * + * @return: 成功则返回TRUE, 失败则返回FALSE + */ +extern bool pbuf_copy_data_in(pbuf_t *const pbuf, + const uint8_t *const src, + uint8_t len); + +/** + * 从pbuf的数据区拷贝数据,并移动data_p指针,不改变data_len + * + * @param dst: 目的地址的指针 + * @param pbuf: 源地址pbuf的指针(从pbuf->data_p开始拷贝) + * @param len: 需要拷贝的数据长度 + * + * @return: 成功则返回TRUE, 失败则返回 + */ +extern bool pbuf_copy_data_out(uint8_t *const dst, + pbuf_t *const pbuf, + uint8_t len); +#endif /* COMPONENTS_COMMON_INCLUDE_PBUF_H_ */ diff --git a/User/lib/inc/sqqueue.h b/User/lib/inc/sqqueue.h new file mode 100644 index 0000000..e6e92c7 --- /dev/null +++ b/User/lib/inc/sqqueue.h @@ -0,0 +1,49 @@ +/** + * @file sqqueue.h + * @author xxx + * @date 2023-06-25 13:07:02 + * @brief 提供循环队列功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __SQQUEUE_H +#define __SQQUEUE_H +#include +#include "data_type_def.h" + +typedef struct _sqqueue_t +{ + uint8_t *base; // 队列存储元素的首地址 + uint8_t entry_size; // 队列元素的宽度 + uint16_t sqq_len; // 队列总长 + uint16_t front; // 队列头下标 + uint16_t rear; // 队列尾下标 +} sqqueue_t; + +/** + * 通用循环队列伪类 + * 该队列有九个操作,分别为单元素入队列、多元素入队列、出队列, + * 单元素撤销入队列(队尾删除)、取队列长度、判空、清空队列、遍历和删除指定位置 + */ +typedef struct _sqqueue_ctrl_t +{ + sqqueue_t sqq; + bool (*enter)(struct _sqqueue_ctrl_t *const p_this, const void *const e); // 单元素入队列 + bool (*string_enter)(struct _sqqueue_ctrl_t *const p_this, const void *const string, uint16_t len); // 多元素入队列 + void *(*del)(struct _sqqueue_ctrl_t *const p_this); // 出队列 + void *(*revoke)(struct _sqqueue_ctrl_t *const p_this); // 撤销入队列 + uint16_t (*get_len)(const struct _sqqueue_ctrl_t *const p_this); // 取队列长度 + bool (*full)(const struct _sqqueue_ctrl_t *const p_this); // 判满 + void (*clear_sqq)(struct _sqqueue_ctrl_t *const p_this); // 清空队列 + void (*traverse)(struct _sqqueue_ctrl_t *const p_this, void (*vi)(const void *e)); // 遍历 + void (*remove)(struct _sqqueue_ctrl_t *const p_this, uint16_t location); // 删除指定位置 +} sqqueue_ctrl_t; + +bool sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this, + uint8_t entry_size, + uint16_t sqq_len); ///< 初始化 + +#endif +/** + * @} + */ diff --git a/User/lib/menu/menu.c b/User/lib/menu/menu.c new file mode 100644 index 0000000..64ccdec --- /dev/null +++ b/User/lib/menu/menu.c @@ -0,0 +1,901 @@ +#include "menu.h" +#include +#include +#ifdef _COT_MENU_USE_MALLOC_ +#include +#endif + +#ifdef _COT_MENU_USE_SHORTCUT_ +#include +#endif + +/* private typedef ---------------------------------------------------------------------------------------------------*/ +typedef struct menu_ctrl +{ + uint16_t parent_window_no; /*!< 父菜单的窗口号 */ + struct menu_ctrl *p_parent_menu_ctrl; /*!< 父菜单控制处理 */ + char *(psz_desc[MENU_SUPPORT_LANGUAGE]); /*!< 当前选项的字符串描述(多语种) */ + showmenu_call_fun_f pfn_show_menu_fun; /*!< 当前菜单显示效果函数 */ + menu_list_t *p_menu_list; /*!< 当前菜单列表 */ + menu_call_fun_f pfn_load_call_fun; /*!< 当前菜单加载函数 */ + menu_call_fun_f pfn_run_call_fun; /*!< 当前选项的非菜单功能函数 */ + menusize_t items_num; /*!< 当前菜单选项总数目 */ + menusize_t show_base_item; /*!< 当前菜单首个显示的选项 */ + menusize_t select_item; /*!< 当前菜单选中的选项 */ + BOOL is_selected; /*!< 菜单选项是否已经被选择 */ +} menu_ctrl_t; + +typedef struct +{ + menu_ctrl_t *p_menu_ctrl; /*!< 当前菜单控制处理 */ + menu_call_fun_f pfn_main_enter_call_fun; /*!< 主菜单进入时(进入菜单)需要执行一次的函数 */ + menu_call_fun_f pfn_main_exit_call_fun; /*!< 主菜单进入后退出时(退出菜单)需要执行一次的函数 */ + menu_call_fun_f pfn_load_call_fun; /*!< 重加载函数 */ + uint8_t language; /*!< 语种选择 */ + BOOL is_enter_main_menu : TRUE; /*!< 是否进入了主菜单 */ +} menu_manage_t; + +/* private define ----------------------------------------------------------------------------------------------------*/ +/* private macro -----------------------------------------------------------------------------------------------------*/ +/* private variables -------------------------------------------------------------------------------------------------*/ +static menu_manage_t sg_t_menu_manage; + +#ifndef _menu_use_malloc_ +static menu_ctrl_t sg_arr_menu_ctrl[MENU_MAX_DEPTH]; +#endif + +static uint8_t sg_curr_menu_depth = 0; + +/* private function prototypes ---------------------------------------------------------------------------------------*/ +static menu_ctrl_t *new_menu(void); +static void delete_menu(menu_ctrl_t *p_menu); + +/* private function --------------------------------------------------------------------------------------------------*/ +/** + * @brief 新建菜单层级 + * + * @return menu_ctrl_t* + */ +static menu_ctrl_t *new_menu(void) +{ + menu_ctrl_t *p_menu_ctrl = NULL; + + if (sg_curr_menu_depth < MENU_MAX_DEPTH) + { +#ifdef _menu_use_malloc_ + p_menu_ctrl = (menu_ctrl_t *)malloc(sizeof(menu_ctrl_t)); +#else + p_menu_ctrl = &sg_arr_menu_ctrl[sg_curr_menu_depth]; +#endif + sg_curr_menu_depth++; + } + + return p_menu_ctrl; +} + +/** + * @brief 销毁菜单层级 + * + * @param p_menu + */ +static void delete_menu(menu_ctrl_t *p_menu) +{ +#ifdef _menu_use_malloc_ + free(p_menu); +#endif + if (sg_curr_menu_depth > 0) + { + sg_curr_menu_depth--; + } +} + +/** + * @brief 解绑当前菜单 + * @return {*} + * @note + */ +BOOL menu_unbind(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL) + { + return FALSE; + } + + delete_menu(sg_t_menu_manage.p_menu_ctrl); + return TRUE; +} + +/** + * @brief 菜单初始化 + * + * @param[in] p_main_menu 主菜单注册信息 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_init(const main_menu_cfg_t *p_main_menu) +{ + int i; + menu_ctrl_t *p_new_menu_ctrl = NULL; + + if (sg_t_menu_manage.p_menu_ctrl != NULL) + { + return FALSE; + } + +#if MENU_MAX_DEPTH != 0 + sg_curr_menu_depth = 0; +#endif + + if ((p_new_menu_ctrl = new_menu()) == NULL) + { + return FALSE; + } + + sg_t_menu_manage.language = 0; + + for (i = 0; i < MENU_SUPPORT_LANGUAGE; i++) + { + p_new_menu_ctrl->psz_desc[i] = (char *)p_main_menu->psz_desc[i]; + } + + p_new_menu_ctrl->p_parent_menu_ctrl = NULL; + p_new_menu_ctrl->pfn_load_call_fun = p_main_menu->pfn_load_call_fun; + p_new_menu_ctrl->pfn_show_menu_fun = NULL; + p_new_menu_ctrl->pfn_run_call_fun = p_main_menu->pfn_run_call_fun; + + p_new_menu_ctrl->p_menu_list = NULL; + p_new_menu_ctrl->items_num = 0; + p_new_menu_ctrl->select_item = 0; + p_new_menu_ctrl->show_base_item = 0; + + sg_t_menu_manage.p_menu_ctrl = p_new_menu_ctrl; + sg_t_menu_manage.is_enter_main_menu = 0; + sg_t_menu_manage.pfn_main_enter_call_fun = p_main_menu->pfn_enter_call_fun; + sg_t_menu_manage.pfn_main_exit_call_fun = p_main_menu->pfn_exit_call_fun; + sg_t_menu_manage.pfn_load_call_fun = p_new_menu_ctrl->pfn_load_call_fun; + + return TRUE; +} + +/** + * @brief 菜单反初始化 + * + * @attention 不管处于任何界面都会逐级退出到主菜单后(会调用退出函数),再退出主菜单,最后反初始化 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_de_init(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL) + { + return FALSE; + } + + menu_main_exit(); + + delete_menu(sg_t_menu_manage.p_menu_ctrl); + sg_t_menu_manage.p_menu_ctrl = NULL; + sg_t_menu_manage.language = 0; + sg_t_menu_manage.is_enter_main_menu = 0; + sg_t_menu_manage.pfn_main_enter_call_fun = NULL; + sg_t_menu_manage.pfn_main_exit_call_fun = NULL; + sg_t_menu_manage.pfn_load_call_fun = NULL; + + return TRUE; +} + +/** + * @brief 子菜单绑定当前菜单选项 + * + * @param parent_window_no 父菜单选项的窗口号 + * @param p_menu_list 新的菜单列表 + * @param menu_num 新的菜单列表数目 + * @param pfn_show_menu_fun 新的菜单列表显示效果回调函数, 为NULL则延续上级菜单显示效果 + * @return BOOL + */ +BOOL menu_bind(uint16_t parent_window_no, const menu_list_t *p_menu_list, menusize_t menu_num, showmenu_call_fun_f pfn_show_menu_fun) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL) + { + return FALSE; + } + + if (sg_t_menu_manage.p_menu_ctrl->p_menu_list != NULL) + { + return TRUE; + } + + sg_t_menu_manage.p_menu_ctrl->p_menu_list = (menu_list_t *)p_menu_list; + sg_t_menu_manage.p_menu_ctrl->items_num = menu_num; + sg_t_menu_manage.p_menu_ctrl->parent_window_no = parent_window_no; + + if (pfn_show_menu_fun != NULL) + { + sg_t_menu_manage.p_menu_ctrl->pfn_show_menu_fun = pfn_show_menu_fun; + } + + return TRUE; +} + +/** + * @brief 选择语种 + * + * @param[in] language_idx 语种索引 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_select_language(uint8_t language_idx) +{ + if (MENU_SUPPORT_LANGUAGE <= language_idx) + { + return FALSE; + } + + sg_t_menu_manage.language = language_idx; + return TRUE; +} + +/** + * @brief 复位菜单, 回到主菜单界面 + * + * @note 该复位回到主菜单不会执行退出所需要执行的回调函数 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_reset(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + while (sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl != NULL) + { + menu_ctrl_t *p_menu_ctrl = sg_t_menu_manage.p_menu_ctrl; + + sg_t_menu_manage.p_menu_ctrl = sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl; + delete_menu(p_menu_ctrl); + } + + sg_t_menu_manage.p_menu_ctrl->select_item = 0; + + return TRUE; +} + +/** + * @brief 主菜单进入 + * + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_main_enter(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 1) + { + return FALSE; + } + + if (sg_t_menu_manage.pfn_main_enter_call_fun != NULL) + { + sg_t_menu_manage.pfn_main_enter_call_fun(); + } + + sg_t_menu_manage.is_enter_main_menu = 1; + sg_t_menu_manage.pfn_load_call_fun = sg_t_menu_manage.p_menu_ctrl->pfn_load_call_fun; + + return TRUE; +} + +/** + * @brief 主菜单退出 + * + * @attention 不管处于任何界面都会逐级退出到主菜单后(会调用退出函数),再退出主菜单 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_main_exit(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + while (menu_exit(1) == 0) + { + } + + if (sg_t_menu_manage.pfn_main_exit_call_fun != NULL) + { + sg_t_menu_manage.pfn_main_exit_call_fun(); + } + + sg_t_menu_manage.is_enter_main_menu = 0; + + return TRUE; +} + +/** + * @brief 进入当前菜单选项 + * + * @param[in] p 传递给进入函数的参数 != NULL 执行进入函数 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_enter(void *p) +{ + int i; + menu_ctrl_t *p_new_menu_ctrl = NULL; + menu_ctrl_t *p_curr_menu_ctrl = sg_t_menu_manage.p_menu_ctrl; + + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + if ((p_new_menu_ctrl = new_menu()) == NULL) + { + return FALSE; + } + + for (i = 0; i < MENU_SUPPORT_LANGUAGE; i++) + { + p_new_menu_ctrl->psz_desc[i] = (char *)p_curr_menu_ctrl->p_menu_list[p_curr_menu_ctrl->select_item].psz_desc[i]; + } + + p_new_menu_ctrl->p_menu_list = NULL; + p_new_menu_ctrl->items_num = 0; + p_new_menu_ctrl->pfn_show_menu_fun = p_curr_menu_ctrl->pfn_show_menu_fun; + p_new_menu_ctrl->pfn_load_call_fun = p_curr_menu_ctrl->p_menu_list[p_curr_menu_ctrl->select_item].pfn_load_call_fun; + p_new_menu_ctrl->pfn_run_call_fun = p_curr_menu_ctrl->p_menu_list[p_curr_menu_ctrl->select_item].pfn_run_call_fun; + p_new_menu_ctrl->select_item = 0; + p_new_menu_ctrl->is_selected = TRUE; + p_new_menu_ctrl->p_parent_menu_ctrl = p_curr_menu_ctrl; + + sg_t_menu_manage.p_menu_ctrl = p_new_menu_ctrl; + sg_t_menu_manage.pfn_load_call_fun = p_new_menu_ctrl->pfn_load_call_fun; + + if (p_curr_menu_ctrl->p_menu_list[p_curr_menu_ctrl->select_item].pfn_enter_call_fun != NULL) + { + p_curr_menu_ctrl->p_menu_list[p_curr_menu_ctrl->select_item].pfn_enter_call_fun(); + } + + return TRUE; +} + +/** + * @brief 退出当前选项并返回上一层菜单 + * + * @param[in] is_reset 菜单选项是否从头选择 + * @return TRUE:成功;FALSE:失败, 即目前处于主菜单, 无法返回 + */ +BOOL menu_exit(BOOL is_reset) +{ + menu_ctrl_t *p_menu_ctrl = sg_t_menu_manage.p_menu_ctrl; + + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + if (sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl == NULL) + { + return FALSE; + } + + sg_t_menu_manage.p_menu_ctrl = sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl; + sg_t_menu_manage.pfn_load_call_fun = sg_t_menu_manage.p_menu_ctrl->pfn_load_call_fun; + delete_menu(p_menu_ctrl); + p_menu_ctrl = NULL; + + if (sg_t_menu_manage.p_menu_ctrl->p_menu_list[sg_t_menu_manage.p_menu_ctrl->select_item].pfn_exit_call_fun != NULL) + { + sg_t_menu_manage.p_menu_ctrl->is_selected = FALSE; + sg_t_menu_manage.p_menu_ctrl->p_menu_list[sg_t_menu_manage.p_menu_ctrl->select_item].pfn_exit_call_fun(); + } + + if (is_reset) + { + sg_t_menu_manage.p_menu_ctrl->select_item = 0; + } + + return TRUE; +} + +/** + * @brief 选择上一个菜单选项 + * + * @param[in] is_allow_roll 第一个选项时是否从跳转到最后一个选项 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_select_previous(BOOL is_allow_roll) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + if (sg_t_menu_manage.p_menu_ctrl->select_item > 0) + { + sg_t_menu_manage.p_menu_ctrl->select_item--; + } + else + { + if (is_allow_roll) + { + sg_t_menu_manage.p_menu_ctrl->select_item = sg_t_menu_manage.p_menu_ctrl->items_num - 1; + } + else + { + sg_t_menu_manage.p_menu_ctrl->select_item = 0; + return FALSE; + } + } + + return TRUE; +} + +/** + * @brief 选择菜单的上一页 + * @param[in] show_num 每页菜单项数目 + * @return {*} + * @note + */ +BOOL menu_select_previous_page(uint8_t show_num) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + uint8_t page_no = sg_t_menu_manage.p_menu_ctrl->select_item / show_num; + if (page_no > 0) + { + sg_t_menu_manage.p_menu_ctrl->select_item = (page_no - 1) * show_num; + sg_t_menu_manage.p_menu_ctrl->show_base_item = 0; + } + else + { + sg_t_menu_manage.p_menu_ctrl->select_item = ((sg_t_menu_manage.p_menu_ctrl->items_num - 1) / show_num) * show_num; + sg_t_menu_manage.p_menu_ctrl->show_base_item = 0; + } + return TRUE; +} + +/** + * @brief 选择下一个菜单选项 + * + * @param[in] is_allow_roll 最后一个选项时是否跳转到第一个选项 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_select_next(BOOL is_allow_roll) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + if (sg_t_menu_manage.p_menu_ctrl->select_item < (sg_t_menu_manage.p_menu_ctrl->items_num - 1)) + { + sg_t_menu_manage.p_menu_ctrl->select_item++; + } + else + { + if (is_allow_roll) + { + sg_t_menu_manage.p_menu_ctrl->select_item = 0; + } + else + { + sg_t_menu_manage.p_menu_ctrl->select_item = sg_t_menu_manage.p_menu_ctrl->items_num - 1; + return FALSE; + } + } + + return TRUE; +} + +/** + * @brief 选择菜单的下一页 + * @param[in] show_num 每页菜单项数目 + * @return {*} + * @note + */ +BOOL menu_select_next_page(uint8_t show_num) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + uint8_t page_no = sg_t_menu_manage.p_menu_ctrl->select_item / show_num; + if (page_no < ((sg_t_menu_manage.p_menu_ctrl->items_num - 1) / show_num)) + { + sg_t_menu_manage.p_menu_ctrl->select_item = (page_no + 1) * show_num; + sg_t_menu_manage.p_menu_ctrl->show_base_item = 0; + } + else + { + sg_t_menu_manage.p_menu_ctrl->select_item = 0; + sg_t_menu_manage.p_menu_ctrl->show_base_item = 0; + } + return TRUE; +} + +/** + * @brief 跳转菜单项 + * + * @param[in] index 菜单项 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_jump_item(uint8_t index) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + sg_t_menu_manage.p_menu_ctrl->select_item = index; + sg_t_menu_manage.p_menu_ctrl->show_base_item = 0; + return TRUE; +} + +#ifdef _menu_use_shortcut_ + +/** + * @brief 相对主菜单或当前菜单通过下级各菜单索引快速进入指定选项 + * + * @param[in] is_absolute 是否采用绝对菜单索引(从主菜单开始) + * @param[in] deep 菜单深度,大于 0 + * @param[in] ... 各级菜单索引值(从0开始), 入参个数由 deep 的值决定 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_shortcut_enter(BOOL is_absolute, uint8_t deep, ...) +{ + uint8_t select_deep = 0; + va_list p_item_list; + menusize_t select_item; + + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + if (is_absolute) + { + menu_reset(); + } + + va_start(p_item_list, deep); + + while (select_deep < deep) + { + select_item = va_arg(p_item_list, int); + + if (select_item >= sg_t_menu_manage.p_menu_ctrl->items_num) + { + va_end(p_item_list); + return FALSE; + } + + sg_t_menu_manage.p_menu_ctrl->select_item = select_item; + menu_enter(NULL); + select_deep++; + } + + va_end(p_item_list); + + return TRUE; +} + +#endif + +/** + * @brief 限制当前菜单界面最多显示的菜单数目 + * + * @note 在菜单显示效果回调函数中使用, 使用成员变量 show_base_item 得到显示界面的第一个选项索引 + * @param[in,out] t_menu_show 当前菜单显示信息 + * @param[in,out] show_num 当前菜单中需要显示的选项数目, 根据当前菜单选项的总数得到最终的显示的选项数目 + * @return TRUE:成功;FALSE:失败 + */ +BOOL menu_limit_show_list_num(menu_show_t *pt_menu_show, menusize_t *p_show_num) +{ + if (pt_menu_show == NULL || p_show_num == NULL) + { + return FALSE; + } + + if (*p_show_num > pt_menu_show->items_num) + { + *p_show_num = pt_menu_show->items_num; + } + + if (pt_menu_show->select_item < pt_menu_show->show_base_item) + { + pt_menu_show->show_base_item = pt_menu_show->select_item; + } + else if ((pt_menu_show->select_item - pt_menu_show->show_base_item) >= *p_show_num) + { + pt_menu_show->show_base_item = pt_menu_show->select_item - *p_show_num + 1; + } + else + { + // 保持 + } + pt_menu_show->page_no = pt_menu_show->select_item / *p_show_num; + return TRUE; +} + +/** + * @brief 获取当前父菜单显示信息 + * 如获取当前菜单的二级父菜单信息,level 为2 + * + * @param[out] pt_menu_show 父 n 级菜单显示信息 + * @param[in] level n 级, 大于 0 + * @return int + */ +BOOL menu_query_parent_menu(menu_show_t *pt_menu_show, uint8_t level) +{ + int i; + menu_list_t *p_menu; + menu_ctrl_t *p_menu_ctrl = NULL; + + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + p_menu_ctrl = sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl; + + while (level && p_menu_ctrl != NULL) + { + p_menu = p_menu_ctrl->p_menu_list; + pt_menu_show->items_num = p_menu_ctrl->items_num; + pt_menu_show->select_item = p_menu_ctrl->select_item; + pt_menu_show->show_base_item = p_menu_ctrl->show_base_item; + + pt_menu_show->psz_desc = sg_t_menu_manage.p_menu_ctrl->psz_desc[sg_t_menu_manage.language]; + + for (i = 0; i < pt_menu_show->items_num && i < MENU_MAX_NUM; i++) + { + pt_menu_show->psz_items_desc[i] = (char *)p_menu[i].psz_desc[sg_t_menu_manage.language]; + pt_menu_show->p_items_ex_data[i] = p_menu[i].p_extend_data; + } + + p_menu_ctrl = p_menu_ctrl->p_parent_menu_ctrl; + level--; + } + + if (level != 0 && p_menu_ctrl == NULL) + { + return FALSE; + } + + return TRUE; +} + +/** + * @brief 获取当前菜单选项的描述字符串最大长度 + * + * @param[in] pt_show_info 当前菜单显示信息 + * @return uint8_t + */ +uint8_t menu_psz_desc_max_size(menu_show_t *pt_show_info) +{ + uint8_t i; + uint8_t max_size = 0; + + if (pt_show_info == NULL) + { + return 0; + } + + for (i = 0; i < pt_show_info->items_num; i++) + { + if (strlen(pt_show_info->psz_items_desc[i]) > max_size) + { + max_size = strlen(pt_show_info->psz_items_desc[i]); + } + } + + return max_size; +} + +/** + * @brief 获取文本信息 + * @param {char} *s 返回的文本 + * @param {menu_txt_t} *m_txt 文本内容 + * @return {*} + * @note + */ +void menu_txt_show(char *buf, const menu_txt_t *m_txt) +{ + DBG_ASSERT(buf != NULL __DBG_LINE); + DBG_ASSERT(m_txt != NULL __DBG_LINE); + sprintf(buf, "%s", m_txt->psz_desc[sg_t_menu_manage.language]); +} + +/** + * @brief 通过当前窗口编号进入菜单 + * + * @param[in] no 选项号 + */ +BOOL menu_enter_with_window_no(uint8_t no) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.p_menu_ctrl->items_num == 0) + { + return FALSE; + } + + for (uint8_t i = 0; i < sg_t_menu_manage.p_menu_ctrl->items_num; i++) + { + if (sg_t_menu_manage.p_menu_ctrl->p_menu_list[i].window_no == no) + { + sg_t_menu_manage.p_menu_ctrl->select_item = i; + menu_enter(NULL); + return TRUE; + } + else + { + if (sg_t_menu_manage.p_menu_ctrl->p_menu_list[i].window_no != 0 && + sg_t_menu_manage.p_menu_ctrl->p_menu_list[i].single_page != TRUE) + { + sg_t_menu_manage.p_menu_ctrl->select_item = i; + + menu_enter(NULL); + if (menu_enter_with_window_no(no) == FALSE) + { + menu_exit(FALSE); + } + else + { + return TRUE; + } + } + } + } + return FALSE; +} + +/** + * @brief 获取当前窗口号 + * + * @return uint16_t + */ +uint16_t menu_current_window_no(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL) + { + return 0; + } + + return sg_t_menu_manage.p_menu_ctrl->p_menu_list[sg_t_menu_manage.p_menu_ctrl->select_item].window_no; +} + +/** + * @brief 获取当前父窗口号 + * + * @return uint16_t + */ +uint16_t menu_current_parent_window_no(void) +{ + if (sg_t_menu_manage.p_menu_ctrl == NULL) + { + return 0; + } + return sg_t_menu_manage.p_menu_ctrl->parent_window_no; +} + +/** + * @brief 获取当前父窗口信息 + * + * @param[out] info + * @return BOOL + */ +BOOL menu_get_parent_window_info(menu_show_t *info) +{ + DBG_ASSERT(info != NULL __DBG_LINE); + int i; + menu_ctrl_t *p; + menu_list_t *p_menu_list; + if (sg_t_menu_manage.p_menu_ctrl != NULL && sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl != NULL) + { + p = sg_t_menu_manage.p_menu_ctrl->p_parent_menu_ctrl; + p_menu_list = p->p_menu_list; + info->items_num = p->items_num; + info->select_item = p->select_item; + info->show_base_item = p->show_base_item; + + info->psz_desc = p->psz_desc[sg_t_menu_manage.language]; + if (p_menu_list != NULL) + { + for (i = 0; i < info->items_num && i < MENU_MAX_NUM; i++) + { + info->psz_items_desc[i] = (char *)p_menu_list[i].psz_desc[sg_t_menu_manage.language]; + } + } + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief 获取当前窗口信息 + * + * @param[out] info + * @return BOOL + */ +BOOL menu_get_current_window_info(menu_show_t *info) +{ + DBG_ASSERT(info != NULL __DBG_LINE); + int i; + menu_list_t *p_menu_list; + if (sg_t_menu_manage.p_menu_ctrl != NULL) + { + p_menu_list = sg_t_menu_manage.p_menu_ctrl->p_menu_list; + info->items_num = sg_t_menu_manage.p_menu_ctrl->items_num; + info->select_item = sg_t_menu_manage.p_menu_ctrl->select_item; + info->show_base_item = sg_t_menu_manage.p_menu_ctrl->show_base_item; + + info->psz_desc = sg_t_menu_manage.p_menu_ctrl->psz_desc[sg_t_menu_manage.language]; + if (p_menu_list != NULL) + { + for (i = 0; i < info->items_num && i < MENU_MAX_NUM; i++) + { + info->psz_items_desc[i] = (char *)p_menu_list[i].psz_desc[sg_t_menu_manage.language]; + info->p_items_ex_data[i] = p_menu_list[i].p_extend_data; + } + } + + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief 菜单任务 + * + * @return 0,成功, 处于菜单模式下; -1,失败, 未处于菜单模式下 + */ +BOOL menu_task(void) +{ + int i; + menu_list_t *p_menu_list; + menu_show_t t_menu_show; + + if (sg_t_menu_manage.p_menu_ctrl == NULL || sg_t_menu_manage.is_enter_main_menu == 0) + { + return FALSE; + } + + if (sg_t_menu_manage.pfn_load_call_fun != NULL) + { + sg_t_menu_manage.pfn_load_call_fun(); + sg_t_menu_manage.pfn_load_call_fun = NULL; + } + + if (sg_t_menu_manage.p_menu_ctrl->p_menu_list != NULL) + { + p_menu_list = sg_t_menu_manage.p_menu_ctrl->p_menu_list; + t_menu_show.items_num = sg_t_menu_manage.p_menu_ctrl->items_num; + t_menu_show.select_item = sg_t_menu_manage.p_menu_ctrl->select_item; + t_menu_show.show_base_item = sg_t_menu_manage.p_menu_ctrl->show_base_item; + + t_menu_show.psz_desc = sg_t_menu_manage.p_menu_ctrl->psz_desc[sg_t_menu_manage.language]; + + for (i = 0; i < t_menu_show.items_num && i < MENU_MAX_NUM; i++) + { + t_menu_show.psz_items_desc[i] = (char *)p_menu_list[i].psz_desc[sg_t_menu_manage.language]; + t_menu_show.p_items_ex_data[i] = p_menu_list[i].p_extend_data; + } + + if (sg_t_menu_manage.p_menu_ctrl->pfn_show_menu_fun != NULL) + { + sg_t_menu_manage.p_menu_ctrl->pfn_show_menu_fun(&t_menu_show); + } + + sg_t_menu_manage.p_menu_ctrl->show_base_item = t_menu_show.show_base_item; + } + + if (sg_t_menu_manage.p_menu_ctrl->pfn_run_call_fun != NULL) + { + sg_t_menu_manage.p_menu_ctrl->pfn_run_call_fun(); + } + + return TRUE; +} diff --git a/User/lib/menu/menu.h b/User/lib/menu/menu.h new file mode 100644 index 0000000..387a4c5 --- /dev/null +++ b/User/lib/menu/menu.h @@ -0,0 +1,278 @@ +#ifndef __MENU_H__ +#define __MENU_H__ + +#include "lib.h" + +/******************************************* 配置项 ********************************************************************/ + +/* 定义 _MENU_USE_MALLOC_ 则采用 MALLOC/FREE 的方式实现多级菜单, 否则通过数组的形式 */ +// #define _MENU_USE_MALLOC_ + +/* 定义 _MENU_USE_SHORTCUT_ 则启用快捷菜单选项进入功能 */ +#define _MENU_USE_SHORTCUT_ + +/* 多级菜单深度 */ +#define MENU_MAX_DEPTH 5 + +/* 菜单支持的最大选项数目 */ +#define MENU_MAX_NUM 40 + +/* 菜单支持的语种数目 */ +#define MENU_SUPPORT_LANGUAGE 2 + +/******************************************* 配置项 ********************************************************************/ + +/* exported types ----------------------------------------------------------------------------------------------------*/ + +#if MENU_MAX_NUM < 255 +typedef uint8_t menusize_t; +#else +typedef uint16_t menusize_t; +#endif + +typedef void (*menu_call_fun_f)(void); + +typedef struct +{ + menusize_t items_num; /*!< 当前菜单中选项的总数目 */ + + menusize_t select_item; /*!< 当前菜单中被选中的选项 */ + + menusize_t show_base_item; /*!< 当前菜单首个显示的选项 */ + + uint8_t page_no; /*!< 当前菜单的页码 */ + + char *psz_desc; /*!< 当前菜单的字符串描述 */ + + char *psz_items_desc[MENU_MAX_NUM]; /*!< 当前菜单中所有选项的字符串描述 */ + + void *p_items_ex_data[MENU_MAX_NUM]; /*!< 当前菜单中所有选项注册时的扩展数据 */ +} menu_show_t; + +typedef void (*showmenu_call_fun_f)(menu_show_t *pt_show_info); + +typedef struct +{ + const char *(psz_desc[MENU_SUPPORT_LANGUAGE]); +} menu_txt_t; + +/** + * @brief 菜单信息注册结构体 + * + */ +typedef struct +{ + uint16_t window_no; /*!< 当前菜单的窗口号 */ + + BOOL single_page; /*!< 当前菜单是否为单页 */ + + const char *(psz_desc[MENU_SUPPORT_LANGUAGE]); /*!< 当前选项的字符串描述(多语种) */ + + menu_call_fun_f pfn_enter_call_fun; /*!< 当前菜单选项进入时(从父菜单进入)需要执行一次的函数, 为null不执行 */ + + menu_call_fun_f pfn_exit_call_fun; /*!< 当前菜单选项进入后退出时(退出至父菜单)需要执行一次的函数, 为null不执行 */ + + menu_call_fun_f pfn_load_call_fun; /*!< 当前菜单选项每次加载时(从父菜单进入或子菜单退出)需要执行一次的函数, 为null不执行 */ + + menu_call_fun_f pfn_run_call_fun; /*!< 当前菜单选项的周期调度函数 */ + + void *p_extend_data; /*!< 当前选项的菜单显示效果函数扩展数据入参, 可自行设置该内容 */ +} menu_list_t, menu_item_t; + +/** + * @brief 菜单信息注册结构体 + * + */ +typedef struct +{ + const char *(psz_desc[MENU_SUPPORT_LANGUAGE]); /*!< 当前选项的字符串描述(多语种) */ + + menu_call_fun_f pfn_enter_call_fun; /*!< 主前菜单进入时(进入菜单)需要执行一次的函数, 为null不执行 */ + + menu_call_fun_f pfn_exit_call_fun; /*!< 主前菜单进入后退出时(退出菜单)需要执行一次的函数, 为null不执行 */ + + menu_call_fun_f pfn_load_call_fun; /*!< 主菜单每次加载时需要执行一次的函数, 为null不执行 */ + + menu_call_fun_f pfn_run_call_fun; /*!< 主菜单周期调度函数 */ +} main_menu_cfg_t; + +/* exported constants ------------------------------------------------------------------------------------------------*/ +/* exported macro ----------------------------------------------------------------------------------------------------*/ + +#define COT_GET_MENU_NUM(x) (sizeof(x) / sizeof(menu_list_t)) + +/* exported functions ------------------------------------------------------------------------------------------------*/ + +/* 菜单初始化和反初始化 */ + +extern BOOL menu_init(const main_menu_cfg_t *p_main_menu); +extern BOOL menu_de_init(void); + +extern BOOL menu_unbind(void); + +extern BOOL menu_bind(uint16_t parent_window_no, const menu_list_t *p_menu_list, menusize_t menu_num, showmenu_call_fun_f pfn_show_menu_fun); + +/* 菜单功能设置 */ + +extern BOOL menu_select_language(uint8_t language_idx); + +/* 菜单选项显示时需要使用的功能扩展函数 */ + +extern BOOL menu_limit_show_list_num(menu_show_t *pt_menu_show, menusize_t *p_show_num); +extern BOOL menu_query_parent_menu(menu_show_t *pt_menu_show, uint8_t level); + +/* 菜单操作 */ + +/** + * @brief 进入主菜单 + * @return 进入成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_main_enter(void); + +/** + * @brief 退出主菜单 + * @return 退出成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_main_exit(void); + +/** + * @brief 重置菜单 + * @return 重置成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_reset(void); + +/** + * @brief 进入菜单 + * @param p 指向菜单的指针 + * @return 进入成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_enter(void *p); + +/** + * @brief 退出菜单 + * @param is_reset 是否重置菜单 + * @return 退出成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_exit(BOOL is_reset); + +/** + * @brief 选择上一个菜单项 + * @param is_allow_roll 是否允许循环选择 + * @return 选择成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_select_previous(BOOL is_allow_roll); + +/** + * @brief 选择上一个菜单页 + * @param {uint8_t} show_num 每页菜单项数目 + * @return {*} + * @note + */ +extern BOOL menu_select_previous_page(uint8_t show_num); + +/** + * @brief 选择下一个菜单项 + * @param is_allow_roll 是否允许循环选择 + * @return 选择成功返回TRUE,否则返回FALSE + */ +extern BOOL menu_select_next(BOOL is_allow_roll); + +/** + * @brief 选择下一个菜单页 + * @param {uint8_t} show_num 每页菜单项数目 + * @return {*} + * @note + */ +extern BOOL menu_select_next_page(uint8_t show_num); + +/** + * @brief 跳转到指定菜单页 + * @param {uint8_t} index 菜单项 + * @return {*} + * @note + */ +extern BOOL menu_jump_item(uint8_t index); +/** + * @brief 进入菜单快捷方式 + * + * 该函数用于进入菜单的快捷方式。 + * + * @param is_absolute 是否为绝对路径 + * @param deep 菜单路径的深度 + * @param ... 菜单路径的参数列表 + * @return BOOL 进入菜单是否成功 + */ +extern BOOL menu_shortcut_enter(BOOL is_absolute, uint8_t deep, ...); + +/** + * @brief 获取菜单描述的最大长度 + * + * 该函数用于获取菜单描述的最大长度。 + * + * @param pt_show_info 菜单显示信息的指针 + * @return uint8_t 菜单描述的最大长度 + */ +extern uint8_t menu_psz_desc_max_size(menu_show_t *pt_show_info); + +/** + * @brief 显示菜单文本 + * + * 该函数用于显示菜单的文本。 + * + * @param buf 存储菜单文本的缓冲区 + * @param m_txt 菜单文本的指针 + */ +extern void menu_txt_show(char *buf, const menu_txt_t *m_txt); + +/** + * @brief 进入指定窗口的菜单 + * + * 该函数用于进入指定窗口的菜单。 + * + * @param no 窗口编号 + * @return BOOL 进入菜单是否成功 + */ +extern BOOL menu_enter_with_window_no(uint8_t no); + +/** + * @brief 获取当前父窗口的编号 + * + * 该函数用于获取当前父窗口的编号。 + * + * @return uint16_t 当前父窗口的编号 + */ +extern uint16_t menu_current_parent_window_no(void); + +/** + * @brief 获取当前窗口的编号 + * + * 该函数用于获取当前窗口的编号。 + * + * @return uint16_t 当前窗口的编号 + */ +extern uint16_t menu_current_window_no(void); + +/** + * @brief 获取当前父窗口的信息 + * + * 该函数用于获取当前父窗口的信息。 + * + * @param info 存储当前窗口信息的指针 + * @return BOOL 获取当前窗口信息是否成功 + */ +extern BOOL menu_get_parent_window_info(menu_show_t *info); + +/** + * @brief 获取当前窗口的信息 + * + * 该函数用于获取当前窗口的信息。 + * + * @param info 存储当前窗口信息的指针 + * @return BOOL 获取当前窗口信息是否成功 + */ +extern BOOL menu_get_current_window_info(menu_show_t *info); +/* 菜单轮询处理任务 */ + +extern BOOL menu_task(void); + +#endif // __MENU_H__ diff --git a/User/lib/readme.md b/User/lib/readme.md new file mode 100644 index 0000000..94587c6 --- /dev/null +++ b/User/lib/readme.md @@ -0,0 +1,169 @@ +[TOC] + + +### clist 简单链表 +#### 说明 +- clist是list的简化版,下面给出常用的接口说明 +- 接口说明: +```code + +void clist_init(clist_node_t **ppFirst); ///< 初始化 ,构造一条空的链表 + +void clist_print(clist_node_t *First); ///< 打印链表 + +uint32_t clist_node_count(clist_node_t *First); ///< 获取链表节点数 + +void clist_push_back(clist_node_t **ppFirst, cnode data); ///< 尾部插入 + +void clist_push_front(clist_node_t **ppFirst, cnode data); ///< 头部插入 + +void clist_pop_back(clist_node_t **ppFirst); ///< 尾部删除 + +void clist_pop_front(clist_node_t **ppFirst); ///< 头部删除 + +void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data); ///< 给定结点插入,插入到结点前 + +int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data); ///< 按位置插入 + +void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos); ///< 给定结点删除 + +void clist_remove(clist_node_t **ppFirst, cnode data); ///< 按值删除,只删遇到的第一个 + +void clist_remove_all(clist_node_t **ppFirst, cnode data); ///< 按值删除,删除所有的 + +void clist_destroy(clist_node_t **ppFirst); ///< 销毁 ,需要销毁每一个节点 + +clist_node_t *clist_find(clist_node_t *pFirst, cnode data); ///< 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL + +``` +#### DEMO +- 详细使用请见simple_clist.c +- examples目录内执行```make clist && make run``` + + +### cmd 命令解析器 +#### 说明 +- cmd是一个非常简单好用的命令解析器。 +> 简单来说,我希望我的开发板,可以通过命令执行一些处理,比如说我用串口发一个命令A,开发板就执行A的一些处理,或者,在调试某些AT模组的时候,当我收到模组返回的一些指令后,自动执行一些处理。 +- 接口说明: +```code +REGISTER_CMD(cmd, handler, desc) ///< 注册命令 + +void cmd_init(void); ///< 初始化命令 + +void cmd_parsing(char *str); ///< 命令解析 +``` + +#### DEMO +- 详细使用请见simple_cmd.c +- 该模块不提供GCC编译,只提供KEIL编译和IAR编译 + + + +### data_analysis 数据分析器 +#### 说明 +- data_analysis 是用来处理串口或者其他方式获得的数据,具有识别数据帧起始和结束的功能,只需要定义好识别符以及长度,该模块会将完整的数据帧处理好 +- 接口说明: +```code +typedef void (*data_interupt_cb_t)(uint8_t id, uint8_t ch); ///< 中断回调函数,数据从这里写入 + +extern uint8_t data_read(uint8_t id, void *buffer, uint16_t len); ///< 读取数据 + +extern void data_write(uint8_t id, uint8_t *const string, uint16_t len); ///< TODO 写入数据 + +extern void lock_data(uint8_t data_id); ///< 锁定数据,防止中断写入数据 + +extern void unlock_data(uint8_t data_id); ///< 解锁数据 + +extern data_interupt_cb_t data_fsm_init(uint8_t data_id); ///< 初始化数据状态机 + +extern bool data_reg(uint8_t id, data_reg_t reg); ///< 注册数据 + +extern void data_unreg(uint8_t id); ///< 注销数据 +``` +#### DEMO +- 详细使用请见simple_data_analysis.c +- examples目录内执行```make data_analysis && make run``` + + +### sqqueue(队列) +#### 说明 +- sqqueue 是一个成员变量固定长度的队列 +- 使用的时候先创建一个"sqqueue_ctrl_t"类型的队列对象,调用初始化函数后就可以使用对象中的功能了 + +#### DEMO +- 详细使用请见simple_sqqueue.c +- examples目录内执行```make sqqueue && make run``` + + +### aes(加密) +百度百科 + +#### 说明 + +- 对不同长度的密钥,AES采用不同的加密轮次: + +| 128位 | 192位 | 256位 | +| ------------- | -----------: | :--------: | +| 10 | 12 | 14 | + +- 密钥扩展:简单说就是将原来的密钥扩展到足够用的长度: + + - 128位密钥: 扩展到 11x4x4 + - 192位密钥: 扩展到 13x4x4 + - 256位密钥: 扩展到 15x4x4 + +- AES加密过程是在一个4×4的字节矩阵上运作,所以一次加解密传入的最小块单位为16字节 + + +#### 代码流程 + +```flow +st=>start: 加密开始 +e=>end: 加密结束 +op1=>operation: 加密的数据[简称密文]、密钥(16个字节)、输入数据块和输出数据块 +op2=>operation: 调用接口"aes_set_key",完成密钥的扩展 +op3=>operation: 调用接口"aes_encrypt",完成数据的加密 +st->op1->op2->op3->e +``` +```flow +st=>start: 解密开始 +e=>end: 解密结束 +op1=>operation: 解密的数据[简称密文]、密钥(16个字节)、输入数据块和输出数据块 +op2=>operation: 调用接口"aes_set_key",完成密钥的扩展 +op3=>operation: 调用接口"aes_encrypt",完成数据的解密 +st->op1->op2->op3->e +``` +#### DEMO +- demo中会使用aes中的接口完成简单的加密和解密数据 +- **将aes.h中的AES_ENC_PREKEYED和AES_DEC_PREKEYED置1** +- 详细使用请见simple_aes.c +- examples目录内执行```make aes && make run``` + +### cmac(类CRC) +#### 说明 + +- cmac是一种数据传输检错功能,以保证数据传输的正确性和完整性 +- cmac基本原理是:通过对需要校验的数据奇偶校验、位移、AES加密获取一段16个字节大小的数组 +- **lorawan使用cmac模块给MAC数据和加密数据做校验的优点:效率很高、安全性很高(在校验数据之前调用"AES_CMAC_Update"二次,增加了异变因子)** +- **困惑:为什么不使用CRC32** +- demo中只对需要校验的数据使用"AES_CMAC_Update"一次,无法确定lorawan增加一次"AES_CMAC_Update"的效果如何 + + +#### 代码流程 + +```flow +st=>start: 校验开始 +e=>end: 校验结束 +op1=>operation: 需要校验的数据、密钥、密钥扩展表 +op2=>operation: 调用接口"AES_CMAC_Init",完成密钥扩展表的初始化 +op3=>operation: 调用接口"AES_CMAC_SetKey",完成密钥扩展表数据 +op4=>operation: 调用接口"AES_CMAC_Update",完成数据的奇偶校验 +op5=>operation: 调用接口"AES_CMAC_Final",生成16个字节的校验表 +op6=>operation: 取表4个字节作为校验码 +st->op1->op2->op3->op4->op5->op6->e +``` + +#### DEMO +- 详细使用请见simple_cmac.c +- examples目录内执行```make cmac && make run``` diff --git a/User/lib/src/aes.c b/User/lib/src/aes.c new file mode 100644 index 0000000..bf5fbdf --- /dev/null +++ b/User/lib/src/aes.c @@ -0,0 +1,981 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state (there are options to use 32-bit types if available). + + The combination of mix columns and byte substitution used here is based on + that developed by Karl Malbrain. His contribution is acknowledged. + */ + +/* define if you have a fast memcpy function on your system */ +#if 0 +#define HAVE_MEMCPY +#include +#if defined(_MSC_VER) +#include +#pragma intrinsic(memcpy) +#endif +#endif + +#include +#include + +/* define if you have fast 32-bit types on your system */ +#if (__CORTEX_M != 0) // if Cortex is different from M0/M0+ +#define HAVE_UINT_32T +#endif + +/* define if you don't want any tables */ +#if 1 +#define USE_TABLES +#endif + +/* On Intel Core 2 duo VERSION_1 is faster */ + +/* alternative versions (test for performance on your system) */ +#if 1 +#define VERSION_1 +#endif + +#include "aes.h" + +// #if defined( HAVE_UINT_32T ) +// typedef unsigned long uint32_t; +// #endif + +/* functions for finite field multiplication in the AES Galois field */ + +#define WPOLY 0x011b +#define BPOLY 0x1b +#define DPOLY 0x008d + +#define f1(x) (x) +#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY)) +#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY)) +#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) ^ (((x >> 5) & 4) * WPOLY)) +#define d2(x) (((x) >> 1) ^ ((x)&1 ? DPOLY : 0)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#if defined(USE_TABLES) + +#define sb_data(w) \ + { /* S Box data values */ \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5), \ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76), \ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0), \ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0), \ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), \ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), \ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75), \ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0), \ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84), \ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b), \ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), \ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), \ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5), \ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2), \ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17), \ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73), \ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), \ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), \ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79), \ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9), \ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08), \ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6), \ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), \ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), \ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94), \ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf), \ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68), \ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) \ + } + +#define isb_data(w) \ + { /* inverse S Box data values */ \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38), \ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb), \ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87), \ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb), \ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d), \ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e), \ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2), \ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25), \ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16), \ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92), \ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda), \ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84), \ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a), \ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06), \ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02), \ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b), \ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea), \ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73), \ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85), \ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e), \ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89), \ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b), \ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20), \ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4), \ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31), \ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f), \ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d), \ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef), \ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0), \ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61), \ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26), \ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) \ + } + +#define mm_data(w) \ + { /* basic data for forming finite field tables */ \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07), \ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f), \ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17), \ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f), \ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27), \ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f), \ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37), \ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f), \ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47), \ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f), \ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57), \ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f), \ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67), \ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f), \ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77), \ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f), \ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87), \ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f), \ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97), \ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f), \ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7), \ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf), \ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7), \ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf), \ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7), \ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf), \ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7), \ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf), \ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7), \ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef), \ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7), \ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) \ + } + +static const uint8_t sbox[256] = sb_data(f1); + +#if defined(AES_DEC_PREKEYED) +static const uint8_t isbox[256] = isb_data(f1); +#endif + +static const uint8_t gfm2_sbox[256] = sb_data(f2); +static const uint8_t gfm3_sbox[256] = sb_data(f3); + +#if defined(AES_DEC_PREKEYED) +static const uint8_t gfmul_9[256] = mm_data(f9); +static const uint8_t gfmul_b[256] = mm_data(fb); +static const uint8_t gfmul_d[256] = mm_data(fd); +static const uint8_t gfmul_e[256] = mm_data(fe); +#endif + +#define s_box(x) sbox[(x)] +#if defined(AES_DEC_PREKEYED) +#define is_box(x) isbox[(x)] +#endif +#define gfm2_sb(x) gfm2_sbox[(x)] +#define gfm3_sb(x) gfm3_sbox[(x)] +#if defined(AES_DEC_PREKEYED) +#define gfm_9(x) gfmul_9[(x)] +#define gfm_b(x) gfmul_b[(x)] +#define gfm_d(x) gfmul_d[(x)] +#define gfm_e(x) gfmul_e[(x)] +#endif +#else + +/* this is the high bit of x right shifted by 1 */ +/* position. Since the starting polynomial has */ +/* 9 bits (0x11b), this right shift keeps the */ +/* values of all top bits within a byte */ + +static uint8_t hibit(const uint8_t x) +{ + uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint8_t gf_inv(const uint8_t x) +{ + uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if (x < 2) + return x; + + for (;;) + { + if (n1) + while (n2 >= n1) /* divide polynomial p2 by p1 */ + { + n2 /= n1; /* shift smaller polynomial left */ + p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ + v2 ^= (v1 * n2); /* shift accumulated value and */ + n2 = hibit(p2); /* add into result */ + } + else + return v1; + + if (n2) /* repeat with values swapped */ + while (n1 >= n2) + { + n1 /= n2; + p1 ^= p2 * n1; + v1 ^= v2 * n1; + n1 = hibit(p1); + } + else + return v2; + } +} + +/* The forward and inverse affine transformations used in the S-box */ +uint8_t fwd_affine(const uint8_t x) +{ +#if defined(HAVE_UINT_32T) + uint32_t w = x; + w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); + return 0x63 ^ ((w ^ (w >> 8)) & 0xff); +#else + return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4) ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4); +#endif +} + +uint8_t inv_affine(const uint8_t x) +{ +#if defined(HAVE_UINT_32T) + uint32_t w = x; + w = (w << 1) ^ (w << 3) ^ (w << 6); + return 0x05 ^ ((w ^ (w >> 8)) & 0xff); +#else + return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6) ^ (x >> 7) ^ (x >> 5) ^ (x >> 2); +#endif +} + +#define s_box(x) fwd_affine(gf_inv(x)) +#define is_box(x) gf_inv(inv_affine(x)) +#define gfm2_sb(x) f2(s_box(x)) +#define gfm3_sb(x) f3(s_box(x)) +#define gfm_9(x) f9(x) +#define gfm_b(x) fb(x) +#define gfm_d(x) fd(x) +#define gfm_e(x) fe(x) + +#endif + +#if defined(HAVE_MEMCPY) +#define block_copy_nn(d, s, l) memcpy(d, s, l) +#define block_copy(d, s) memcpy(d, s, N_BLOCK) +#else +#define block_copy_nn(d, s, l) copy_block_nn(d, s, l) +#define block_copy(d, s) copy_block(d, s) +#endif + +static void copy_block(void *d, const void *s) +{ +#if defined(HAVE_UINT_32T) + ((uint32_t *)d)[0] = ((uint32_t *)s)[0]; + ((uint32_t *)d)[1] = ((uint32_t *)s)[1]; + ((uint32_t *)d)[2] = ((uint32_t *)s)[2]; + ((uint32_t *)d)[3] = ((uint32_t *)s)[3]; +#else + ((uint8_t *)d)[0] = ((uint8_t *)s)[0]; + ((uint8_t *)d)[1] = ((uint8_t *)s)[1]; + ((uint8_t *)d)[2] = ((uint8_t *)s)[2]; + ((uint8_t *)d)[3] = ((uint8_t *)s)[3]; + ((uint8_t *)d)[4] = ((uint8_t *)s)[4]; + ((uint8_t *)d)[5] = ((uint8_t *)s)[5]; + ((uint8_t *)d)[6] = ((uint8_t *)s)[6]; + ((uint8_t *)d)[7] = ((uint8_t *)s)[7]; + ((uint8_t *)d)[8] = ((uint8_t *)s)[8]; + ((uint8_t *)d)[9] = ((uint8_t *)s)[9]; + ((uint8_t *)d)[10] = ((uint8_t *)s)[10]; + ((uint8_t *)d)[11] = ((uint8_t *)s)[11]; + ((uint8_t *)d)[12] = ((uint8_t *)s)[12]; + ((uint8_t *)d)[13] = ((uint8_t *)s)[13]; + ((uint8_t *)d)[14] = ((uint8_t *)s)[14]; + ((uint8_t *)d)[15] = ((uint8_t *)s)[15]; +#endif +} + +static void copy_block_nn(uint8_t *d, const uint8_t *s, uint8_t nn) +{ + while (nn--) + //*((uint8_t*)d)++ = *((uint8_t*)s)++; + *d++ = *s++; +} + +static void xor_block(void *d, const void *s) +{ +#if defined(HAVE_UINT_32T) + ((uint32_t *)d)[0] ^= ((uint32_t *)s)[0]; + ((uint32_t *)d)[1] ^= ((uint32_t *)s)[1]; + ((uint32_t *)d)[2] ^= ((uint32_t *)s)[2]; + ((uint32_t *)d)[3] ^= ((uint32_t *)s)[3]; +#else + ((uint8_t *)d)[0] ^= ((uint8_t *)s)[0]; + ((uint8_t *)d)[1] ^= ((uint8_t *)s)[1]; + ((uint8_t *)d)[2] ^= ((uint8_t *)s)[2]; + ((uint8_t *)d)[3] ^= ((uint8_t *)s)[3]; + ((uint8_t *)d)[4] ^= ((uint8_t *)s)[4]; + ((uint8_t *)d)[5] ^= ((uint8_t *)s)[5]; + ((uint8_t *)d)[6] ^= ((uint8_t *)s)[6]; + ((uint8_t *)d)[7] ^= ((uint8_t *)s)[7]; + ((uint8_t *)d)[8] ^= ((uint8_t *)s)[8]; + ((uint8_t *)d)[9] ^= ((uint8_t *)s)[9]; + ((uint8_t *)d)[10] ^= ((uint8_t *)s)[10]; + ((uint8_t *)d)[11] ^= ((uint8_t *)s)[11]; + ((uint8_t *)d)[12] ^= ((uint8_t *)s)[12]; + ((uint8_t *)d)[13] ^= ((uint8_t *)s)[13]; + ((uint8_t *)d)[14] ^= ((uint8_t *)s)[14]; + ((uint8_t *)d)[15] ^= ((uint8_t *)s)[15]; +#endif +} + +static void copy_and_key(void *d, const void *s, const void *k) +{ +#if defined(HAVE_UINT_32T) + ((uint32_t *)d)[0] = ((uint32_t *)s)[0] ^ ((uint32_t *)k)[0]; + ((uint32_t *)d)[1] = ((uint32_t *)s)[1] ^ ((uint32_t *)k)[1]; + ((uint32_t *)d)[2] = ((uint32_t *)s)[2] ^ ((uint32_t *)k)[2]; + ((uint32_t *)d)[3] = ((uint32_t *)s)[3] ^ ((uint32_t *)k)[3]; +#elif 1 + ((uint8_t *)d)[0] = ((uint8_t *)s)[0] ^ ((uint8_t *)k)[0]; + ((uint8_t *)d)[1] = ((uint8_t *)s)[1] ^ ((uint8_t *)k)[1]; + ((uint8_t *)d)[2] = ((uint8_t *)s)[2] ^ ((uint8_t *)k)[2]; + ((uint8_t *)d)[3] = ((uint8_t *)s)[3] ^ ((uint8_t *)k)[3]; + ((uint8_t *)d)[4] = ((uint8_t *)s)[4] ^ ((uint8_t *)k)[4]; + ((uint8_t *)d)[5] = ((uint8_t *)s)[5] ^ ((uint8_t *)k)[5]; + ((uint8_t *)d)[6] = ((uint8_t *)s)[6] ^ ((uint8_t *)k)[6]; + ((uint8_t *)d)[7] = ((uint8_t *)s)[7] ^ ((uint8_t *)k)[7]; + ((uint8_t *)d)[8] = ((uint8_t *)s)[8] ^ ((uint8_t *)k)[8]; + ((uint8_t *)d)[9] = ((uint8_t *)s)[9] ^ ((uint8_t *)k)[9]; + ((uint8_t *)d)[10] = ((uint8_t *)s)[10] ^ ((uint8_t *)k)[10]; + ((uint8_t *)d)[11] = ((uint8_t *)s)[11] ^ ((uint8_t *)k)[11]; + ((uint8_t *)d)[12] = ((uint8_t *)s)[12] ^ ((uint8_t *)k)[12]; + ((uint8_t *)d)[13] = ((uint8_t *)s)[13] ^ ((uint8_t *)k)[13]; + ((uint8_t *)d)[14] = ((uint8_t *)s)[14] ^ ((uint8_t *)k)[14]; + ((uint8_t *)d)[15] = ((uint8_t *)s)[15] ^ ((uint8_t *)k)[15]; +#else + block_copy(d, s); + xor_block(d, k); +#endif +} + +static void add_round_key(uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK]) +{ + xor_block(d, k); +} + +static void shift_sub_rows(uint8_t st[N_BLOCK]) +{ + uint8_t tt; + + st[0] = s_box(st[0]); + st[4] = s_box(st[4]); + st[8] = s_box(st[8]); + st[12] = s_box(st[12]); + + tt = st[1]; + st[1] = s_box(st[5]); + st[5] = s_box(st[9]); + st[9] = s_box(st[13]); + st[13] = s_box(tt); + + tt = st[2]; + st[2] = s_box(st[10]); + st[10] = s_box(tt); + tt = st[6]; + st[6] = s_box(st[14]); + st[14] = s_box(tt); + + tt = st[15]; + st[15] = s_box(st[11]); + st[11] = s_box(st[7]); + st[7] = s_box(st[3]); + st[3] = s_box(tt); +} + +#if defined(AES_DEC_PREKEYED) + +static void inv_shift_sub_rows(uint8_t st[N_BLOCK]) +{ + uint8_t tt; + + st[0] = is_box(st[0]); + st[4] = is_box(st[4]); + st[8] = is_box(st[8]); + st[12] = is_box(st[12]); + + tt = st[13]; + st[13] = is_box(st[9]); + st[9] = is_box(st[5]); + st[5] = is_box(st[1]); + st[1] = is_box(tt); + + tt = st[2]; + st[2] = is_box(st[10]); + st[10] = is_box(tt); + tt = st[6]; + st[6] = is_box(st[14]); + st[14] = is_box(tt); + + tt = st[3]; + st[3] = is_box(st[7]); + st[7] = is_box(st[11]); + st[11] = is_box(st[15]); + st[15] = is_box(tt); +} + +#endif + +#if defined(VERSION_1) +static void mix_sub_columns(uint8_t dt[N_BLOCK]) +{ + uint8_t st[N_BLOCK]; + block_copy(st, dt); +#else +static void mix_sub_columns(uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK]) +{ +#endif + dt[0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]); + dt[1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]); + dt[2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]); + dt[3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]); + + dt[4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]); + dt[5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]); + dt[6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]); + dt[7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]); + + dt[8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]); + dt[9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]); + dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]); + dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]); + + dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]); + dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]); + dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]); + dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]); +} + +#if defined(AES_DEC_PREKEYED) + +#if defined(VERSION_1) +static void inv_mix_sub_columns(uint8_t dt[N_BLOCK]) +{ + uint8_t st[N_BLOCK]; + block_copy(st, dt); +#else +static void inv_mix_sub_columns(uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK]) +{ +#endif + dt[0] = is_box(gfm_e(st[0]) ^ gfm_b(st[1]) ^ gfm_d(st[2]) ^ gfm_9(st[3])); + dt[5] = is_box(gfm_9(st[0]) ^ gfm_e(st[1]) ^ gfm_b(st[2]) ^ gfm_d(st[3])); + dt[10] = is_box(gfm_d(st[0]) ^ gfm_9(st[1]) ^ gfm_e(st[2]) ^ gfm_b(st[3])); + dt[15] = is_box(gfm_b(st[0]) ^ gfm_d(st[1]) ^ gfm_9(st[2]) ^ gfm_e(st[3])); + + dt[4] = is_box(gfm_e(st[4]) ^ gfm_b(st[5]) ^ gfm_d(st[6]) ^ gfm_9(st[7])); + dt[9] = is_box(gfm_9(st[4]) ^ gfm_e(st[5]) ^ gfm_b(st[6]) ^ gfm_d(st[7])); + dt[14] = is_box(gfm_d(st[4]) ^ gfm_9(st[5]) ^ gfm_e(st[6]) ^ gfm_b(st[7])); + dt[3] = is_box(gfm_b(st[4]) ^ gfm_d(st[5]) ^ gfm_9(st[6]) ^ gfm_e(st[7])); + + dt[8] = is_box(gfm_e(st[8]) ^ gfm_b(st[9]) ^ gfm_d(st[10]) ^ gfm_9(st[11])); + dt[13] = is_box(gfm_9(st[8]) ^ gfm_e(st[9]) ^ gfm_b(st[10]) ^ gfm_d(st[11])); + dt[2] = is_box(gfm_d(st[8]) ^ gfm_9(st[9]) ^ gfm_e(st[10]) ^ gfm_b(st[11])); + dt[7] = is_box(gfm_b(st[8]) ^ gfm_d(st[9]) ^ gfm_9(st[10]) ^ gfm_e(st[11])); + + dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15])); + dt[1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15])); + dt[6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15])); + dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15])); +} + +#endif + +#if defined(AES_ENC_PREKEYED) || defined(AES_DEC_PREKEYED) + +/* Set the cipher key for the pre-keyed version */ + +return_type aes_set_key(const uint8_t key[], length_type keylen, aes_context ctx[1]) +{ + uint8_t cc, rc, hi; + + switch (keylen) + { + case 16: + case 24: + case 32: + break; + default: + ctx->rnd = 0; + return (uint8_t)-1; + } + block_copy_nn(ctx->ksch, key, keylen); + hi = (keylen + 28) << 2; + ctx->rnd = (hi >> 4) - 1; + for (cc = keylen, rc = 1; cc < hi; cc += 4) + { + uint8_t tt, t0, t1, t2, t3; + + t0 = ctx->ksch[cc - 4]; + t1 = ctx->ksch[cc - 3]; + t2 = ctx->ksch[cc - 2]; + t3 = ctx->ksch[cc - 1]; + if (cc % keylen == 0) + { + tt = t0; + t0 = s_box(t1) ^ rc; + t1 = s_box(t2); + t2 = s_box(t3); + t3 = s_box(tt); + rc = f2(rc); + } + else if (keylen > 24 && cc % keylen == 16) + { + t0 = s_box(t0); + t1 = s_box(t1); + t2 = s_box(t2); + t3 = s_box(t3); + } + tt = cc - keylen; + ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; + ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; + ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; + ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; + } + return 0; +} + +#endif + +#if defined(AES_ENC_PREKEYED) + +/* Encrypt a single block of 16 bytes */ + +return_type aes_encrypt(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1]) +{ + if (ctx->rnd) + { + uint8_t s1[N_BLOCK], r; + copy_and_key(s1, in, ctx->ksch); + + for (r = 1; r < ctx->rnd; ++r) +#if defined(VERSION_1) + { + mix_sub_columns(s1); + add_round_key(s1, ctx->ksch + r * N_BLOCK); + } +#else + { + uint8_t s2[N_BLOCK]; + mix_sub_columns(s2, s1); + copy_and_key(s1, s2, ctx->ksch + r * N_BLOCK); + } +#endif + shift_sub_rows(s1); + copy_and_key(out, s1, ctx->ksch + r * N_BLOCK); + } + else + return (uint8_t)-1; + return 0; +} + +/* CBC encrypt a number of blocks (input and return an IV) */ + +return_type aes_cbc_encrypt(const uint8_t *in, uint8_t *out, + int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1]) +{ + + while (n_block--) + { + xor_block(iv, in); + if (aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + // memcpy(out, iv, N_BLOCK); + block_copy(out, iv); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_DEC_PREKEYED) + +/* Decrypt a single block of 16 bytes */ + +return_type aes_decrypt(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1]) +{ + if (ctx->rnd) + { + uint8_t s1[N_BLOCK], r; + copy_and_key(s1, in, ctx->ksch + ctx->rnd * N_BLOCK); + inv_shift_sub_rows(s1); + + for (r = ctx->rnd; --r;) +#if defined(VERSION_1) + { + add_round_key(s1, ctx->ksch + r * N_BLOCK); + inv_mix_sub_columns(s1); + } +#else + { + uint8_t s2[N_BLOCK]; + copy_and_key(s2, s1, ctx->ksch + r * N_BLOCK); + inv_mix_sub_columns(s1, s2); + } +#endif + copy_and_key(out, s1, ctx->ksch); + return 0; + } + else + return 1; +} + +/* CBC decrypt a number of blocks (input and return an IV) */ + +return_type aes_cbc_decrypt(const uint8_t *in, uint8_t *out, + int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1]) +{ + while (n_block--) + { + uint8_t tmp[N_BLOCK]; + + // memcpy(tmp, in, N_BLOCK); + block_copy(tmp, in); + if (aes_decrypt(in, out, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + xor_block(out, iv); + // memcpy(iv, tmp, N_BLOCK); + block_copy(iv, tmp); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_ENC_128_OTFK) + +/* The 'on the fly' encryption key update for for 128 bit keys */ + +static void update_encrypt_key_128(uint8_t k[N_BLOCK], uint8_t *rc) +{ + uint8_t cc; + + k[0] ^= s_box(k[13]) ^ *rc; + k[1] ^= s_box(k[14]); + k[2] ^= s_box(k[15]); + k[3] ^= s_box(k[12]); + *rc = f2(*rc); + + for (cc = 4; cc < 16; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_encrypt_128(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK]) +{ + uint8_t s1[N_BLOCK], r, rc = 1; + + if (o_key != key) + block_copy(o_key, key); + copy_and_key(s1, in, o_key); + + for (r = 1; r < 10; ++r) +#if defined(VERSION_1) + { + mix_sub_columns(s1); + update_encrypt_key_128(o_key, &rc); + add_round_key(s1, o_key); + } +#else + { + uint8_t s2[N_BLOCK]; + mix_sub_columns(s2, s1); + update_encrypt_key_128(o_key, &rc); + copy_and_key(s1, s2, o_key); + } +#endif + + shift_sub_rows(s1); + update_encrypt_key_128(o_key, &rc); + copy_and_key(out, s1, o_key); +} + +#endif + +#if defined(AES_DEC_128_OTFK) + +/* The 'on the fly' decryption key update for for 128 bit keys */ + +static void update_decrypt_key_128(uint8_t k[N_BLOCK], uint8_t *rc) +{ + uint8_t cc; + + for (cc = 12; cc > 0; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + *rc = d2(*rc); + k[0] ^= s_box(k[13]) ^ *rc; + k[1] ^= s_box(k[14]); + k[2] ^= s_box(k[15]); + k[3] ^= s_box(k[12]); +} + +/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_decrypt_128(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK]) +{ + uint8_t s1[N_BLOCK], r, rc = 0x6c; + if (o_key != key) + block_copy(o_key, key); + + copy_and_key(s1, in, o_key); + inv_shift_sub_rows(s1); + + for (r = 10; --r;) +#if defined(VERSION_1) + { + update_decrypt_key_128(o_key, &rc); + add_round_key(s1, o_key); + inv_mix_sub_columns(s1); + } +#else + { + uint8_t s2[N_BLOCK]; + update_decrypt_key_128(o_key, &rc); + copy_and_key(s2, s1, o_key); + inv_mix_sub_columns(s1, s2); + } +#endif + update_decrypt_key_128(o_key, &rc); + copy_and_key(out, s1, o_key); +} + +#endif + +#if defined(AES_ENC_256_OTFK) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_encrypt_key_256(uint8_t k[2 * N_BLOCK], uint8_t *rc) +{ + uint8_t cc; + + k[0] ^= s_box(k[29]) ^ *rc; + k[1] ^= s_box(k[30]); + k[2] ^= s_box(k[31]); + k[3] ^= s_box(k[28]); + *rc = f2(*rc); + + for (cc = 4; cc < 16; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box(k[12]); + k[17] ^= s_box(k[13]); + k[18] ^= s_box(k[14]); + k[19] ^= s_box(k[15]); + + for (cc = 20; cc < 32; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ + +void aes_encrypt_256(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK]) +{ + uint8_t s1[N_BLOCK], r, rc = 1; + if (o_key != key) + { + block_copy(o_key, key); + block_copy(o_key + 16, key + 16); + } + copy_and_key(s1, in, o_key); + + for (r = 1; r < 14; ++r) +#if defined(VERSION_1) + { + mix_sub_columns(s1); + if (r & 1) + add_round_key(s1, o_key + 16); + else + { + update_encrypt_key_256(o_key, &rc); + add_round_key(s1, o_key); + } + } +#else + { + uint8_t s2[N_BLOCK]; + mix_sub_columns(s2, s1); + if (r & 1) + copy_and_key(s1, s2, o_key + 16); + else + { + update_encrypt_key_256(o_key, &rc); + copy_and_key(s1, s2, o_key); + } + } +#endif + + shift_sub_rows(s1); + update_encrypt_key_256(o_key, &rc); + copy_and_key(out, s1, o_key); +} + +#endif + +#if defined(AES_DEC_256_OTFK) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_decrypt_key_256(uint8_t k[2 * N_BLOCK], uint8_t *rc) +{ + uint8_t cc; + + for (cc = 28; cc > 16; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box(k[12]); + k[17] ^= s_box(k[13]); + k[18] ^= s_box(k[14]); + k[19] ^= s_box(k[15]); + + for (cc = 12; cc > 0; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + *rc = d2(*rc); + k[0] ^= s_box(k[29]) ^ *rc; + k[1] ^= s_box(k[30]); + k[2] ^= s_box(k[31]); + k[3] ^= s_box(k[28]); +} + +/* Decrypt a single block of 16 bytes with 'on the fly' + 256 bit keying +*/ +void aes_decrypt_256(const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK]) +{ + uint8_t s1[N_BLOCK], r, rc = 0x80; + + if (o_key != key) + { + block_copy(o_key, key); + block_copy(o_key + 16, key + 16); + } + + copy_and_key(s1, in, o_key); + inv_shift_sub_rows(s1); + + for (r = 14; --r;) +#if defined(VERSION_1) + { + if ((r & 1)) + { + update_decrypt_key_256(o_key, &rc); + add_round_key(s1, o_key + 16); + } + else + add_round_key(s1, o_key); + inv_mix_sub_columns(s1); + } +#else + { + uint8_t s2[N_BLOCK]; + if ((r & 1)) + { + update_decrypt_key_256(o_key, &rc); + copy_and_key(s2, s1, o_key + 16); + } + else + copy_and_key(s2, s1, o_key); + inv_mix_sub_columns(s1, s2); + } +#endif + copy_and_key(out, s1, o_key); +} + +#endif diff --git a/User/lib/src/clist.c b/User/lib/src/clist.c new file mode 100644 index 0000000..fb54261 --- /dev/null +++ b/User/lib/src/clist.c @@ -0,0 +1,338 @@ +/** + * @file clist.c + * @author xxx + * @date 2023-08-08 23:18:09 + * @brief + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "clist.h" + +/** + * @brief 初始化链表 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @return void + * @note 初始化链表,将链表头节点设置为空 + */ +void clist_init(clist_node_t **ppFirst) +{ + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + *ppFirst = NULL; +} + +/** + * @brief 打印链表 + * @param {clist_node_t} First 链表头节点 + * @return void + * @note 打印链表中的所有节点数据 + */ +void clist_print(clist_node_t *First) +{ + LOG_PRINT("list: "); + for (clist_node_t *p = First; p != NULL; p = p->Next) + LOG_PRINT("%d-->", p->data); + LOG_PRINT("\n"); +} + +/** + * @brief 获取链表节点数 + * @param {clist_node_t} First 链表头节点 + * @return {uint32_t} 链表节点数 + * @note 遍历链表,计算节点数 + */ +uint32_t clist_node_count(clist_node_t *First) +{ + int32_t count = 0; + for (clist_node_t *p = First; p != NULL; p = p->Next) + count++; + return count; +} + +/** + * @brief 申请新节点 + * @param {cnode} data 节点数据 + * @return {clist_node_t *} 新节点指针 + * @note 分配内存,创建新节点 + */ +static clist_node_t *CreateNode(cnode data) +{ + clist_node_t *node = (clist_node_t *)osel_mem_alloc(sizeof(clist_node_t)); + node->data = data; + node->Next = NULL; + return node; +} + +/** + * @brief 尾部插入 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @param {cnode} data 要插入的节点数据 + * @return void + * @note 在链表末尾插入一个新节点,新节点数据为data + */ +void clist_push_back(clist_node_t **ppFirst, cnode data) +{ + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + clist_node_t *node = CreateNode(data); + if (*ppFirst == NULL) // 判断链表不为空 + { + *ppFirst = node; + return; + } + // 找链表中的最后一个节点 + clist_node_t *p = *ppFirst; + while (p->Next != NULL) + p = p->Next; + p->Next = node; // 插入新申请的节点 +} + +/** + * @brief 头部插入 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @param {cnode} data 要插入的节点数据 + * @return void + * @note 在链表头部插入一个新节点,新节点数据为data + */ +void clist_push_front(clist_node_t **ppFirst, cnode data) +{ + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + clist_node_t *node = CreateNode(data); + node->Next = *ppFirst; + *ppFirst = node; +} + +/** + * @brief 尾部删除 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @return void + * @note 删除链表中最后一个节点 + */ +void clist_pop_back(clist_node_t **ppFirst) // 尾部删除 +{ + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + DBG_ASSERT(*ppFirst != NULL __DBG_LINE); + if ((*ppFirst)->Next == NULL) + { + osel_mem_free(*ppFirst); + *ppFirst = NULL; + return; + } + clist_node_t *p = *ppFirst; + while (p->Next->Next != NULL) + p = p->Next; + osel_mem_free(p->Next); + p->Next = NULL; +} + +/** + * @brief 头部删除 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @return void + * @note 删除链表中第一个节点 + */ +void clist_pop_front(clist_node_t **ppFirst) +{ + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + DBG_ASSERT(*ppFirst != NULL __DBG_LINE); // 链表不是空链表 + clist_node_t *first = *ppFirst; + *ppFirst = (*ppFirst)->Next; + osel_mem_free(first); +} +/** + * @brief 按节点指针插入 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @param {clist_node_t} *pPos 要插入的节点位置 + * @param {cnode} data 要插入的节点数据 + * @return void + * @note 在指定节点位置插入一个新节点,新节点数据为data + */ +void clist_insert_for_node(clist_node_t **ppFirst, clist_node_t *pPos, cnode data) +{ + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + if (*ppFirst == pPos) + { + clist_push_front(ppFirst, data); + return; + } + clist_node_t *newNode = CreateNode(data); + clist_node_t *p; + + for (p = *ppFirst; p->Next != pPos; p = p->Next) + { + } // 找到pos前的一个节点 + p->Next = newNode; // 改变的是字段内的值,而不是指针的值 + newNode->Next = pPos; +} +/** + * @brief 按位置插入 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @param {int32_t} Pos 插入位置 + * @param {cnode} data 要插入的节点数据 + * @return {int32_t} 插入成功返回1,否则返回0 + * @note 在指定位置插入一个新节点,新节点数据为data + */ +int32_t clist_insert(clist_node_t **ppFirst, int32_t Pos, cnode data) // 按位置插入 +{ + clist_node_t *p = *ppFirst; + for (int32_t i = 0; i < Pos; i++) + { + if (p == NULL) + return 0; + p = p->Next; + } + clist_insert_for_node(ppFirst, p, data); + return 1; +} + +/** + * @brief 按位置删除 + * @param {clist_node_t} **ppFirst 指向链表头节点的指针 + * @param {int32_t} Pos 要删除的节点位置 + * @return {int32_t} 删除成功返回1,否则返回0 + * @note 从指定位置删除一个节点 + */ +int32_t cListErase(clist_node_t **ppFirst, int32_t Pos) +{ + clist_node_t *p = *ppFirst; + for (int32_t i = 0; i < Pos; i++) + { + if (p == NULL) + return 0; + p = p->Next; + } + clist_erase_for_node(ppFirst, p); + return 1; +} + +/** + * @brief 删除给定结点之后的所有结点 + * @param {clist_node_t **} ppFirst 指向链表头结点的指针 + * @param {clist_node_t *} pPos 要删除的结点 + * @return void + * @note + */ +void clist_erase_for_node(clist_node_t **ppFirst, clist_node_t *pPos) +{ + if (*ppFirst == pPos) + { + clist_pop_front(ppFirst); + return; + } + clist_node_t *p = *ppFirst; + while (p->Next != pPos) + p = p->Next; + p->Next = pPos->Next; + osel_mem_free(pPos); +} + +/** + * @brief 删除指定值的结点 + * @param {clist_node_t **} ppFirst 指向链表头结点的指针 + * @param {cnode} data 要删除的结点数据 + * @return void + * @note + */ +void clist_remove(clist_node_t **ppFirst, cnode data) +{ + clist_node_t *p = *ppFirst; + clist_node_t *prev = NULL; + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + if (*ppFirst == NULL) + return; + while (p) + { + if (p->data == data) + { + if (*ppFirst == p) // 删除的是第一个节点 + { + *ppFirst = p->Next; + osel_mem_free(p); + p = NULL; + } + else // 删除中间节点 + { + prev->Next = p->Next; + osel_mem_free(p); + p = NULL; + } + break; + } + prev = p; + p = p->Next; + } +} + +/** + * @brief 删除指定值的所有结点 + * @param {clist_node_t **} ppFirst 指向链表头结点的指针 + * @param {cnode} data 要删除的结点数据 + * @return void + * @note + */ +void clist_remove_all(clist_node_t **ppFirst, cnode data) +{ + clist_node_t *p = NULL; + clist_node_t *prev = NULL; + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + if (*ppFirst == NULL) + return; + p = *ppFirst; + while (p) + { + if (p->data == data) + { + if (*ppFirst == p) // 删除的是第一个节点 + { + *ppFirst = p->Next; + osel_mem_free(p); + p = *ppFirst; + } + else // 删除中间节点 + { + prev->Next = p->Next; + osel_mem_free(p); + p = prev; + } + } + prev = p; + p = p->Next; + } +} + +/** + * @brief 销毁链表,每个节点都要销毁 + * @param {clist_node_t **} ppFirst 指向链表头结点的指针 + * @return void + * @note + */ +void clist_destroy(clist_node_t **ppFirst) +{ + clist_node_t *p = NULL; + clist_node_t *del = NULL; + DBG_ASSERT(ppFirst != NULL __DBG_LINE); + p = *ppFirst; + while (p) + { + del = p; + p = p->Next; + osel_mem_free(del); + del = NULL; + } + *ppFirst = NULL; +} + +/** + * @brief 按值查找,返回第一个找到的结点指针,如果没找到,返回 NULL + * @param {clist_node_t *} pFirst 指向链表头结点的指针 + * @param {cnode} data 要查找的结点数据 + * @return {clist_node_t *} 找到的结点指针,如果没有找到,返回 NULL + * @note + */ +clist_node_t *clist_find(clist_node_t *pFirst, cnode data) +{ + for (clist_node_t *p = pFirst; p != NULL; p = p->Next) + { + if (p->data == data) + return p; + } + return NULL; +} diff --git a/User/lib/src/cmac.c b/User/lib/src/cmac.c new file mode 100644 index 0000000..3d7f81d --- /dev/null +++ b/User/lib/src/cmac.c @@ -0,0 +1,159 @@ +/************************************************************************** +Copyright (C) 2009 Lander Casado, Philippas Tsigas + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +In no event shall the authors or copyright holders be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever resulting from loss of use, data or profits, whether or not +advised of the possibility of damage, and on any theory of liability, +arising out of or in connection with the use or performance of this software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE + +*****************************************************************************/ +// #include +// #include +#include +#include "aes.h" +#include "cmac.h" +#include "osel_arch.h" + +#define LSHIFT(v, r) \ + do \ + { \ + int32_t i; \ + for (i = 0; i < 15; i++) \ + (r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \ + (r)[15] = (v)[15] << 1; \ + } while (0) + +#define XOR(v, r) \ + do \ + { \ + int32_t i; \ + for (i = 0; i < 16; i++) \ + { \ + (r)[i] = (r)[i] ^ (v)[i]; \ + } \ + } while (0) + +void AES_CMAC_Init(AES_CMAC_CTX *ctx) +{ + osel_memset(ctx->X, 0, sizeof ctx->X); + ctx->M_n = 0; + osel_memset(ctx->rijndael.ksch, '\0', 240); +} + +void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]) +{ + // rijndael_set_key_enc_only(&ctx->rijndael, key, 128); + aes_set_key(key, AES_CMAC_KEY_LENGTH, &ctx->rijndael); +} + +void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len) +{ + uint32_t mlen; + uint8_t in[16]; + + if (ctx->M_n > 0) + { + mlen = MIN(16 - ctx->M_n, len); + osel_memcpy(ctx->M_last + ctx->M_n, data, mlen); + ctx->M_n += mlen; + if (ctx->M_n < 16 || len == mlen) + return; + XOR(ctx->M_last, ctx->X); + // rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); + aes_encrypt(ctx->X, ctx->X, &ctx->rijndael); + data += mlen; + len -= mlen; + } + while (len > 16) /* not last block */ + { + + XOR(data, ctx->X); + // rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); + + osel_memcpy(in, &ctx->X[0], 16); // Bestela ez du ondo iten + aes_encrypt(in, in, &ctx->rijndael); + osel_memcpy(&ctx->X[0], in, 16); + + data += 16; + len -= 16; + } + /* potential last block, save it */ + osel_memcpy(ctx->M_last, data, len); + ctx->M_n = len; +} + +void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx) +{ + uint8_t K[16]; + uint8_t in[16]; + /* generate subkey K1 */ + osel_memset(K, '\0', 16); + + // rijndael_encrypt(&ctx->rijndael, K, K); + + aes_encrypt(K, K, &ctx->rijndael); + + if (K[0] & 0x80) + { + LSHIFT(K, K); + K[15] ^= 0x87; + } + else + LSHIFT(K, K); + + if (ctx->M_n == 16) + { + /* last block was a complete block */ + XOR(K, ctx->M_last); + } + else + { + /* generate subkey K2 */ + if (K[0] & 0x80) + { + LSHIFT(K, K); + K[15] ^= 0x87; + } + else + LSHIFT(K, K); + + /* padding(M_last) */ + ctx->M_last[ctx->M_n] = 0x80; + while (++ctx->M_n < 16) + ctx->M_last[ctx->M_n] = 0; + + XOR(K, ctx->M_last); + } + XOR(ctx->M_last, ctx->X); + + // rijndael_encrypt(&ctx->rijndael, ctx->X, digest); + + osel_memcpy(in, &ctx->X[0], 16); // Bestela ez du ondo iten + aes_encrypt(in, digest, &ctx->rijndael); + osel_memset(K, 0, sizeof K); +} diff --git a/User/lib/src/cmd.c b/User/lib/src/cmd.c new file mode 100644 index 0000000..8a8a26d --- /dev/null +++ b/User/lib/src/cmd.c @@ -0,0 +1,111 @@ +/** + * @file cmd.c + * @author xxx + * @date 2023-06-25 13:07:02 + * @brief 命令解析器 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "cmd.h" + +#include + +static cmd_t *_cmd_begin, *_cmd_end; + +static int _cmd_to_lower(int c) +{ + if ((c >= 'A') && (c <= 'Z')) + return c + ('a' - 'A'); + return c; +} + +static unsigned int _cmd_hash(const char *str) +{ + int tmp, c = *str; + unsigned int seed = CMD_HASH; /* 'jiejie' string hash */ + unsigned int hash = 0; + + while (*str) + { + tmp = _cmd_to_lower(c); + hash = (hash ^ seed) + tmp; + str++; + c = *str; + } + return hash; +} + +static void _cmd_init(const void *begin, const void *end) +{ + _cmd_begin = (cmd_t *)begin; + _cmd_end = (cmd_t *)end; +} + +static cmd_t *_get_next_cmd(cmd_t *cmd) +{ + unsigned int *ptr; + ptr = (unsigned int *)(cmd + 1); + while ((*ptr == 0) && ((unsigned int *)ptr < (unsigned int *)_cmd_end)) + ptr++; + + return (cmd_t *)ptr; +} + +static int _cmd_match(const char *str, const char *cmd) +{ + int c1, c2; + + do + { + c1 = _cmd_to_lower(*str++); + c2 = _cmd_to_lower(*cmd++); + } while ((c1 == c2) && c1); + + return c1 - c2; +} + +static void _list(void) +{ + cmd_t *index; + for (index = _cmd_begin; index < _cmd_end; index = _get_next_cmd(index)) + { + // printf("%s -->%s\n", index->cmd, index->cmd_mess); + } +} +REGISTER_CMD(_list, _list, list all command); + +void cmd_init(void) +{ + cmd_t *index; + +#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */ + extern const int CMDS$$Base; + extern const int CMDS$$Limit; + _cmd_init(&CMDS$$Base, &CMDS$$Limit); +#elif defined(__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */ + _cmd_init(__section_begin("CMDS"), __section_end("CMDS")); +#endif + + for (index = _cmd_begin; index < _cmd_end; index = _get_next_cmd(index)) + { + index->hash = _cmd_hash(index->cmd); + } +} + +void cmd_parsing(char *str) +{ + cmd_t *index; + unsigned int hash = _cmd_hash(str); + + for (index = _cmd_begin; index < _cmd_end; index = _get_next_cmd(index)) + { + if (hash == index->hash) + { + if (_cmd_match(str, index->cmd) == 0) + { + index->handler(); + break; + } + } + } +} diff --git a/User/lib/src/data_analysis.c b/User/lib/src/data_analysis.c new file mode 100644 index 0000000..76993f4 --- /dev/null +++ b/User/lib/src/data_analysis.c @@ -0,0 +1,468 @@ +/** + * @file data_analysis.c + * @author xxx + * @date 2023-06-25 13:07:02 + * @brief 处理传输层的数据 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include +#include "../inc/data_analysis.h" +#include "../inc/sqqueue.h" +#include "../inc/debug.h" + +typedef uint8_t data_entry_t; +typedef void (*state_t)(uint8_t data_id, uint8_t sig, uint8_t ch); + +typedef enum _event /* enumeration */ +{ + SD_SIG, + LD_SIG, + CHAR_SIG, + ED_SIG, +} sig_event; + +typedef struct _fsm_t_ +{ + state_t current_state; +} fsm_t; + +typedef struct _DATA_frm_t_ +{ + uint8_t sd_index; + + struct + { + uint8_t data[DATA_LD_LEN_MAX]; + uint8_t index; + uint16_t frm_len; + } ld; // length describe + + uint16_t payload_len; // actually len of recvived data + uint8_t ed_index; + + uint16_t last_enter_q_num; // record the num of frames has entered the queue + uint8_t locked; + uint8_t sig; +} data_frm_t; + +#define TRAN(state) (fsm[data_id].current_state = (state_t)(state)) +#define FSM_DISPATCH(data_id, sig, ch) (fsm[data_id].current_state((data_id), (sig), (ch))) + +static fsm_t fsm[DATA_NUM] = {0}; + +static data_frm_t data_frm_array[DATA_NUM]; +static data_reg_t data_reg_array[DATA_NUM]; + +static sqqueue_ctrl_t data_recv_sqq[DATA_NUM]; + +static void wait_sd_state(uint8_t data_id, uint8_t sig, uint8_t ch); +/** + * @brief 加锁数据 + * @param {uint8_t} data_id + * @note + */ +void lock_data(uint8_t data_id) +{ + data_frm_array[data_id].locked = TRUE; // 设置数据帧结构体的锁定标志为TRUE + for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++) // 遍历数据接收缓冲区,删除所有已入队项 + { + data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]); // 删除项 + } + + data_frm_array[data_id].last_enter_q_num = 0; // 重置最后进入队列的项数量 + data_frm_array[data_id].sd_index = 0; // 重置SD索引 + data_frm_array[data_id].ed_index = 0; // 重置ED索引 + data_frm_array[data_id].ld.frm_len = 0; // 重置数据帧长度 + data_frm_array[data_id].payload_len = 0; // 重置负载长度 + + TRAN(wait_sd_state); // 切换到等待SD状态 +} + +/** + * @brief 解锁数据 + * @param {uint8_t} data_id + * @note + */ +void unlock_data(uint8_t data_id) +{ + TRAN(wait_sd_state); // 切换到等待SD状态 + + data_frm_array[data_id].last_enter_q_num = 0; // 重置最后进入队列的项数量 + data_frm_array[data_id].sd_index = 0; // 重置SD索引 + data_frm_array[data_id].ed_index = 0; // 重置ED索引 + data_frm_array[data_id].ld.frm_len = 0; // 重置数据帧长度 + data_frm_array[data_id].payload_len = 0; // 重置负载长度 + + data_frm_array[data_id].locked = FALSE; // 设置数据帧结构体的锁定标志为FALSE +} + +/** + * @brief 处理结束状态 + * @param {uint8_t} data_id + * @param {uint8_t} sig + * @param {uint8_t} ch + * @note + */ +static void end_state_handle(uint8_t data_id, uint8_t sig, uint8_t ch) +{ + TRAN(wait_sd_state); // 切换到等待SD状态 + data_frm_array[data_id].ld.frm_len = 0; // 重置数据帧长度 + data_frm_array[data_id].payload_len = 0; // 重置负载长度 + data_frm_array[data_id].last_enter_q_num = 0; // 重置最后进入队列的项数量 + if (data_reg_array[data_id].func_ptr != NULL) // 如果数据项注册了处理函数 + { + (*(data_reg_array[data_id].func_ptr))(); // 调用处理函数 + } +} + +/** + * @brief 这个函数处理等待结束状态。 + * @param {uint8_t} data_id - 数据的ID。 + * @param {uint8_t} sig - 信号。 + * @param {uint8_t} ch - 通道。 + * @return {*} + * @note + */ +static void wait_end_state(uint8_t data_id, uint8_t sig, uint8_t ch) +{ + // 如果数据寄存器数组无效 + if (!data_reg_array[data_id].ed.valid) + { + // 如果数据帧数组的帧长度为0 + if (data_frm_array[data_id].ld.frm_len == 0) + { + // 转换到等待SD状态 + TRAN(wait_sd_state); + + // 处理结束状态 + end_state_handle(data_id, sig, ch); + + // 对于数据帧数组的最后一个进入队列的数量,撤销数据接收队列 + for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++) + { + data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]); + } + // 将数据帧数组的最后一个进入队列的数量设置为0 + data_frm_array[data_id].last_enter_q_num = 0; + } + else + { + // 如果数据接收队列进入成功 + if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch)) + { + // 增加数据帧数组的最后一个进入队列的数量 + data_frm_array[data_id].last_enter_q_num++; + // 如果增加的数据帧数组的有效载荷长度等于数据帧数组的帧长度 + if (++data_frm_array[data_id].payload_len == + data_frm_array[data_id].ld.frm_len) + { + // 处理结束状态 + end_state_handle(data_id, sig, ch); + } + } + else + { + // 锁定数据 + lock_data(data_id); + } + } + } + else + { + // 如果数据帧数组的帧长度为0 + if (data_frm_array[data_id].ld.frm_len == 0) + { + // 如果数据接收队列进入成功 + if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch)) + { + // 增加数据帧数组的最后一个进入队列的数量 + data_frm_array[data_id].last_enter_q_num++; + // 如果数据寄存器数组的数据等于通道 + if (data_reg_array[data_id].ed.data[0] == ch) + { + // 处理结束状态 + end_state_handle(data_id, sig, ch); + } + } + else + { + // 锁定数据 + lock_data(data_id); + } + } + else + { + // 如果数据接收队列进入成功 + if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch)) + { + // 增加数据帧数组的最后一个进入队列的数量 + data_frm_array[data_id].last_enter_q_num++; + // 如果增加的数据帧数组的有效载荷长度大于等于数据帧数组的帧长度减去数据寄存器数组的位置 + if (++data_frm_array[data_id].payload_len >= + data_frm_array[data_id].ld.frm_len - data_reg_array[data_id].ld.pos) + { + // 如果数据寄存器数组的数据等于通道 + if (data_reg_array[data_id].ed.data[0] == ch) + { + // 处理结束状态 + end_state_handle(data_id, sig, ch); + } + } + } + else + { + // 锁定数据 + lock_data(data_id); + } + } + } +} + +/** + * @brief 处理等待LD状态 + * @param {uint8_t} data_id + * @param {uint8_t} sig + * @param {uint8_t} ch + * @return {*} + * @note + */ +static void wait_ld_state(uint8_t data_id, uint8_t sig, uint8_t ch) +{ + if (!data_reg_array[data_id].ld.valid) // 如果数据项未注册LD状态 + { + TRAN(wait_end_state); // 切换到等待结束状态 + FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch); // 调用FSM处理函数 + return; + } + data_frm_array[data_id].ld.data[data_frm_array[data_id].ld.index++] = ch; // 将字符添加到数据帧中 + if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch)) // 尝试进入队列 + { + data_frm_array[data_id].last_enter_q_num++; // 增加最后进入队列的项数量 + if (data_frm_array[data_id].ld.index == data_reg_array[data_id].ld.len) // 如果索引等于数据项长度 + { + if (data_reg_array[data_id].ld.little_endian == TRUE) // 如果小端存储 + { + data_frm_array[data_id].ld.frm_len = + data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 1] * 256 + + data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 2]; + } + else + { + data_frm_array[data_id].ld.frm_len = + data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 2] * 256 + + data_frm_array[data_id].ld.data[DATA_LD_LEN_MAX - 1]; + } + + if (data_reg_array[data_id].ld.len == 1) // 如果是只有1个字节长度的数据 + { + data_frm_array[data_id].ld.frm_len = data_frm_array[data_id].ld.data[0]; + } + + if ((data_frm_array[data_id].ld.frm_len > data_reg_array[data_id].argu.len_max) || (data_frm_array[data_id].ld.frm_len < data_reg_array[data_id].argu.len_min)) + { + data_frm_array[data_id].ld.index = 0; + TRAN(wait_sd_state); // 切换到等待SD状态 + + for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++) + { + data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]); // 删除项 + } + + data_frm_array[data_id].ld.frm_len = 0; + data_frm_array[data_id].last_enter_q_num = 0; + } + else + { + data_frm_array[data_id].ld.index = 0; + TRAN(wait_end_state); // 切换到等待结束状态 + } + } + } + else + { + lock_data(data_id); // 锁定数据 + } +} +/** + * @brief 等待SD状态处理函数 + * @param {uint8_t} data_id 数据ID + * @param {uint8_t} sig 信号 + * @param {uint8_t} ch 字符 + * @return {*} + * @note + */ +static void wait_sd_state(uint8_t data_id, uint8_t sig, uint8_t ch) +{ + // 如果数据寄存器中的SD数据无效 + if (!data_reg_array[data_id].sd.valid) + { + // transition to wait_ld_state状态 + TRAN(wait_ld_state); + // 调用数据帧数组中对应的数据帧处理函数 + FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch); + return; + } + // 如果数据寄存器中的SD数据中的当前字节等于输入的字节 + if (data_reg_array[data_id].sd.data[data_frm_array[data_id].sd_index++] == ch) + { + // 如果输入字符串成功进入队列 + if (data_recv_sqq[data_id].enter(&data_recv_sqq[data_id], (void *)&ch)) + { + // 更新数据帧数组中对应的数据帧的最后一个进入队列的队列号 + data_frm_array[data_id].last_enter_q_num++; + // 如果数据帧中的SD数据索引等于数据寄存器中的SD数据长度 + if (data_frm_array[data_id].sd_index == data_reg_array[data_id].sd.len) + { + // 更新数据帧中的SD数据索引为0 + data_frm_array[data_id].sd_index = 0; + // transition to wait_ld_state状态 + TRAN(wait_ld_state); + } + } + // 如果输入字符串无法进入队列 + else + { + // 锁定数据 + lock_data(data_id); + } + } + // 如果数据寄存器中的SD数据中的当前字节不等于输入的字节 + else + { + // 遍历并删除队列中的输入字符串 + for (uint8_t i = 0; i < data_frm_array[data_id].last_enter_q_num; i++) + { + data_recv_sqq[data_id].revoke(&data_recv_sqq[data_id]); + } + + // 更新数据帧中的SD数据索引为0 + data_frm_array[data_id].sd_index = 0; + // 更新数据帧中的最后一个进入队列的队列号为0 + data_frm_array[data_id].last_enter_q_num = 0; + } +} + +/** + * @brief 处理数据字符 + * @param {uint8_t} data_id + * @param {uint8_t} ch + * @return {*} + * @note + */ +static void data_char_handle(uint8_t data_id, uint8_t ch) +{ + // 如果数据ID对应的数据寄存器的回显使能标志为真 + if (data_reg_array[data_id].echo_en) + { + // 将输入字符写入数据寄存器 + data_write(data_id, &ch, 1); + } + + // 调用数据帧数组中对应的数据帧处理函数 + FSM_DISPATCH(data_id, data_frm_array[data_id].sig, ch); +} + +/** + * @brief 初始化数据帧处理机 + * @param {uint8_t} data_id + * @return {*} + * @note + */ +data_interupt_cb_t data_fsm_init(uint8_t data_id) +{ + TRAN(wait_sd_state); // 切换到等待SD状态 + data_reg_array[data_id].func_ptr = NULL; // 设置数据ID寄存器的回调函数为空 + memset(&data_frm_array[data_id], 0, sizeof(data_frm_t)); // 初始化数据帧结构体 + data_frm_array[data_id].sig = CHAR_SIG; // 设置数据帧签名 + + if (sqqueue_ctrl_init(&data_recv_sqq[data_id], + sizeof(data_entry_t), + DATA_BUF_RECV_SQQ_LEN) == FALSE) // 初始化数据接收缓冲区 + { + DBG_ASSERT(FALSE __DBG_LINE); // 如果初始化失败,输出调试信息 + } + + return data_char_handle; // 返回数据处理回调函数指针 +} +/** + * @brief 读取数据 + * @param {uint8_t} id + * @param {void} *buffer + * @param {uint16_t} len + * @return {*} + * @note + */ +uint8_t data_read(uint8_t id, void *buffer, uint16_t len) +{ + uint8_t i = 0; + data_entry_t e; + uint8_t *buf = (uint8_t *)buffer; + + // 如果接收队列中存在长度大于等于输入长度的数据项 + if (data_recv_sqq[id].get_len(&data_recv_sqq[id]) >= len) + { + // 遍历接收队列并读取数据项到缓冲区 + for (i = 0; i < len; i++) + { + e = *((data_entry_t *)data_recv_sqq[id].del(&data_recv_sqq[id])); + buf[i] = e; + } + } + // 如果接收队列中不存在长度大于等于输入长度的数据项 + else + { + // 遍历接收队列并读取数据项到缓冲区 + while ((data_recv_sqq[id].get_len(&data_recv_sqq[id]) != 0) && (i < len)) + { + e = *((data_entry_t *)data_recv_sqq[id].del(&data_recv_sqq[id])); + buf[i++] = e; + } + } + + // 如果数据帧数组中对应的数据帧被锁定 + if (data_frm_array[id].locked) + { + // 解锁数据 + unlock_data(id); + } + + return i; +} + +/** + * @brief + * @param {uint8_t} id + * @param {uint8_t} *string + * @param {uint16_t} len + * @return {*} + * @note + */ +void data_write(uint8_t id, uint8_t *const string, uint16_t len) +{ +} + +/** + * @brief 设置数据寄存器 + * @param {uint8_t} id + * @param {data_reg_t} reg + * @return {*} + * @note + */ +BOOL data_reg(uint8_t id, data_reg_t reg) +{ + if (data_reg_array[id].func_ptr == NULL) + { + memcpy((void *)&data_reg_array[id], (void *)®, sizeof(reg)); + return TRUE; + } + else + { + return FALSE; + } +} +void data_unreg(uint8_t id) +{ + memset((void *)&data_reg_array[id], 0, sizeof(data_reg_t)); + data_reg_array[id].func_ptr = NULL; +} diff --git a/User/lib/src/debug.c b/User/lib/src/debug.c new file mode 100644 index 0000000..5d1c690 --- /dev/null +++ b/User/lib/src/debug.c @@ -0,0 +1,45 @@ +/* + * @File: debug.c + * @Descripttion: + * @Version: 1.0 + * @Author: + * @Date: 2022-12-10 20:15:01 + * @LastEditors: xxx + * @LastEditTime: 2023-08-08 14:39:18 + */ +#include "../inc/debug.h" + +#ifndef STM32 +BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_) +{ + do + { + if ((cond) == FALSE) + { + LOG_ERR("DBG_ASSERT:%d", line); + return FALSE; + } + } while (__LINE__ == -1); + return TRUE; +} + +#else +#define __no_init __attribute__((zero_init)) // 变量不初始化为0,keil下需要定义,并在options for target中设置noInit + +uint16_t dbg_line; +BOOL DBG_ASSERT(uint8_t cond _DBG_LINE_) +{ + do + { + if ((cond) == FALSE) + { + dbg_line = line; + while (1) + { + LOG_ERR("DBG_ASSERT:%d", line); + } + } + } while (__LINE__ == -1); + return TRUE; +} +#endif diff --git a/User/lib/src/filter.c b/User/lib/src/filter.c new file mode 100644 index 0000000..86110ed --- /dev/null +++ b/User/lib/src/filter.c @@ -0,0 +1,160 @@ +#include "filter.h" +#include +#include "osel_arch.h" +// 卡尔曼滤波 +#define FILTER_COUNT 10 +void kalman_init(kalman_t *cfg) +{ + cfg->Last_P = 1; + cfg->Now_P = 0; + cfg->out = 0; + cfg->Kg = 0; + cfg->Q = 0; + cfg->R = 0.05; + cfg->filter_count = 0; + if (cfg->default_filter_count == 0) + { + cfg->default_filter_count = FILTER_COUNT; + } + if (cfg->filter_limit == 0) + { + cfg->filter_limit = 1.0f; // 限制滤波器的最大误差 + } + + cfg->change = TRUE; +} + +void kalman_reset(kalman_t *cfg) +{ + kalman_init(cfg); +} + +float32 kalman_update(kalman_t *cfg, float32 input) +{ + if (fabs(input - cfg->out) > cfg->filter_limit) + { + if (cfg->filter_count < cfg->default_filter_count) + { + cfg->filter_count++; + cfg->change = FALSE; + } + else + { + kalman_init(cfg); + } + } + else + { + cfg->filter_count = 0; + cfg->change = FALSE; + } + + // 预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差 + cfg->Now_P = cfg->Last_P + cfg->Q; + // 卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差) + cfg->Kg = cfg->Now_P / (cfg->Now_P + cfg->R); + // 更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值) + cfg->out = cfg->out + cfg->Kg * (input - cfg->out); // 因为这一次的预测值就是上一次的输出值 + // 更新协方差方程: 本次的系统协方差付给 cfg->LastP 威下一次运算准备。 + cfg->Last_P = (1 - cfg->Kg) * cfg->Now_P; + return cfg->out; +} + +// 一阶滞后滤波法 +void lpf_init(lpf_t *cfg) +{ + cfg->fisrt_flag = TRUE; + cfg->last_value = 0; + if (cfg->alpha <= 0 || cfg->alpha > 1) + { + cfg->alpha = 0.3f; + } +} + +float32 lpf_update(lpf_t *cfg, float32 input) +{ + float32 out; + + /***************** 如果第一次进入,则给 out_last 赋值 ******************/ + if (TRUE == cfg->fisrt_flag) + { + cfg->fisrt_flag = FALSE; + cfg->last_value = input; + } + + /*************************** 一阶滤波 *********************************/ + out = cfg->alpha * input + (1 - cfg->alpha) * cfg->last_value; + cfg->last_value = out; + + return out; +} + +void lpf_reset(lpf_t *cfg) +{ + cfg->fisrt_flag = TRUE; +} + +/** + * 滑动平均窗口滤波 + */ +lpf_window_t *lpf_window_init(uint16_t size) +{ + lpf_window_t *cfg = (lpf_window_t *)osel_mem_alloc(sizeof(lpf_window_t)); + DBG_ASSERT(cfg != NULL __DBG_LINE); + osel_memset((uint8_t *)cfg, 0, sizeof(lpf_window_t)); + cfg->size = size; + cfg->window = (float32 *)osel_mem_alloc(sizeof(float32) * size); + DBG_ASSERT(cfg->window != NULL __DBG_LINE); + cfg->index = 0; + cfg->sum = 0; + return cfg; +} + +void lpf_window_dinit(lpf_window_t *cfg) +{ + if (cfg != NULL) + { + if (cfg->window != NULL) + { + osel_mem_free(cfg->window); + } + osel_mem_free(cfg); + } +} + +// 滑动平均窗口重置 +void lpf_window_reset(lpf_window_t *cfg) +{ + DBG_ASSERT(cfg != NULL __DBG_LINE); + cfg->index = 0; + cfg->sum = 0; + osel_memset((uint8_t *)cfg->window, 0, sizeof(float32) * cfg->size); +} + +float32 lpf_window_update(lpf_window_t *cfg, float32 input) +{ + DBG_ASSERT(cfg != NULL __DBG_LINE); + cfg->sum = 0; + // 如果窗口未满,直接添加新值到当前索引位置 + if (cfg->index < cfg->size) + { + cfg->window[cfg->index++] = input; + } + else + { + // 如果窗口已满,替换最旧的值 + for (uint16_t i = 0; i < cfg->size - 1; i++) + { + cfg->window[i] = cfg->window[i + 1]; + } + cfg->window[cfg->size - 1] = input; + } + // 计算窗口中所有值的和 + for (uint16_t i = 0; i < cfg->index; i++) + { + cfg->sum += cfg->window[i]; + } + // 计算平均值 + cfg->out = cfg->sum / cfg->index; + return cfg->out; +} diff --git a/User/lib/src/lib.c b/User/lib/src/lib.c new file mode 100644 index 0000000..8d983b2 --- /dev/null +++ b/User/lib/src/lib.c @@ -0,0 +1,440 @@ +/* + * @Author: + * @day: 2023-04-11 08:21:19 + * @LastEditors: xxx + * @LastEditTime: 2023-08-15 10:14:58 + * @Description: + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "../inc/lib.h" +#include +#include + +const uint8_t _days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +const uint16_t _month_days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; +static uint32_t crc32_table[256]; // CRC32表 + +uint32_t cpu_encrypt(void) +{ + uint32_t cpuid[3]; + // 获取CPU唯一的ID + cpuid[0] = *(uint32_t *)(UID_BASE); + cpuid[1] = *(uint32_t *)(UID_BASE + 4); + cpuid[2] = *(uint32_t *)(UID_BASE + 8); + // 加密算法,很简单的加密算法 + uint32_t encrypt_code = (cpuid[0] >> 3) + (cpuid[1] >> 1) + (cpuid[2] >> 2); + return encrypt_code; +} + +// 判断加密 +BOOL cpu_judge_encrypt(uint32_t cupid_encrypt) +{ + uint32_t cpuid[4]; + // 获取CPU唯一的ID + cpuid[0] = *(uint32_t *)(UID_BASE); + cpuid[1] = *(uint32_t *)(UID_BASE + 4); + cpuid[2] = *(uint32_t *)(UID_BASE + 8); + // 加密算法,很简单的加密算法 + cpuid[3] = (cpuid[0] >> 3) + (cpuid[1] >> 1) + (cpuid[2] >> 2); + // 检查Flash中的UID是否合法 + return (cupid_encrypt == cpuid[3]); +} + +/** + * @brief Generate the CRC32 lookup table. + * + * This function generates the CRC32 lookup table used for fast computation of the + * CRC32 checksum. The table is generated using the polynomial 0xEDB88320, which is a + * common polynomial used in CRC32 calculations. + */ +static void generate_crc32_table() +{ + static BOOL is_init = FALSE; + if (is_init) + { + return; + } + uint32_t polynomial = 0xEDB88320; + for (uint32_t i = 0; i < 256; i++) + { + uint32_t crc = i; + for (uint32_t j = 0; j < 8; j++) + { + crc = (crc & 1) ? (crc >> 1) ^ polynomial : crc >> 1; + } + crc32_table[i] = crc; + } + is_init = TRUE; +} + +/** + * @brief 版本号1.0拆解成1和0 + * @param {uint8_t} *version_str + * @param {uint8_t} *hi + * @param {uint8_t} *lo + * @return {*} + */ +void version_split(uint8_t *version_str, uint8_t *hi, uint8_t *lo) +{ + uint8_t flag = 1; + + for (uint8_t i = 0; version_str[i] != '\0'; i++) + { + if (version_str[i] == '.') + { + flag = 0; + continue; + } + + if (flag) + { + *hi = *hi * 10 + (version_str[i] - '0'); + } + else + { + *lo = *lo * 10 + (version_str[i] - '0'); + } + } +} + +// 反序数组 +void reverse(uint8_t *buf, uint16_t len) +{ + uint8_t tmp; + uint16_t i; + for (i = 0; i < len / 2; i++) + { + tmp = buf[i]; + buf[i] = buf[len - i - 1]; + buf[len - i - 1] = tmp; + } +} + +/*** + * @brief 判断是否在数组中 + * @param {uint8_t} *arr 数组 + * @param {uint8_t} len 数组长度 + * @param {uint8_t} val 要判断的值 + * @return {*} TRUE: 在数组中 + */ +BOOL is_in_array(uint16_t *arr, uint16_t len, uint16_t val) +{ + uint16_t i; + for (i = 0; i < len; i++) + { + if (arr[i] == val) + { + return TRUE; + } + } + return FALSE; +} + +/** + * 计算并返回指定数据区域crc的值 + * + * @param data: 待计算的数据区首地址 + * @param length: 待计算的数据区长度 + * + * @return crc计算的结果 + */ +uint16_t crc16_compute(const uint8_t *const data, uint16_t length) +{ + uint16_t crcVal = 0xffff; + const uint8_t *ptr = data; + + for (uint16_t i = 0; i < length; i++) + { + crcVal ^= (uint16_t)*ptr++; + + for (uint8_t j = 0; j < 8; j++) + { + if (crcVal & 0x0001) + { + crcVal = (crcVal >> 1) ^ 0x8401; + } + else + { + crcVal >>= 1; + } + } + } + + return crcVal; +} + +/** + * @brief Calculate the CRC32 value of a data buffer. + * + * This function calculates the CRC32 value of a data buffer using the lookup table method. + * The lookup table is generated using the polynomial 0xEDB88320, which is a common polynomial used in CRC32 calculations. + * + * @param data The data buffer to calculate the CRC32 value of. + * @param length The length of the data buffer in bytes. + * @return The CRC32 value of the data buffer. + */ +uint32_t crc32_compute(const uint8_t *const data, uint16_t length) +{ + generate_crc32_table(); + uint32_t crc = 0xFFFFFFFF; + for (size_t i = 0; i < length; i++) + { + crc = (crc >> 8) ^ crc32_table[(crc ^ data[i]) & 0xFF]; + } + return crc ^ 0xFFFFFFFF; +} + +/** + * 计算并返回指定数据区域异或的值 + * + * @param data: 待计算的数据区首地址 + * @param length: 待计算的数据区长度 + * + * @return 异或计算的结果 + */ +uint8_t xor_compute(const uint8_t *const data, uint16_t length) +{ + uint16_t i; + const uint8_t *ptr = data; + uint8_t xor = 0; + for (i = 0; i < length; i++) + { + xor ^= *ptr; + ptr++; + } + return xor; +} + +// 通过bit位获取置1个数量 +uint8_t get_bit_num(uint8_t bit) +{ + uint8_t num = 0; + while (bit) + { + if (bit & 0x01) + { + num++; + } + bit >>= 1; + } + return num; +} + +// 通过bit位获取置1的位置 +BOOL is_bit_set(int x, int k) +{ + int mask = 1 << k; + return (x & mask) != 0; +} + +// 判断数组是否全是同一个值 +BOOL is_same_value(uint8_t *buf, uint16_t len, uint8_t value) +{ + uint16_t i; + for (i = 0; i < len; i++) + { + if (buf[i] != value) + { + return FALSE; + } + } + return TRUE; +} + +// 检查是否是闰年 +uint8_t isLeap(uint16_t year) +{ + return (year % 400 == 0) || (year % 100 != 0 && year % 4 == 0); +} + +// 计算一年中的第几天 +uint16_t dayOfyear(uint16_t year, uint8_t month, uint8_t day) +{ + uint8_t month_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + uint16_t total; + total = day; + if (month > 2 && isLeap(year)) + total += 1; + for (uint8_t i = 0; i < month - 1; i++) + { + total += month_days[i]; + } + return total; +} + +// 计算一年中的第几周 +uint16_t weekOfyear(uint16_t year, uint8_t month, uint8_t day) +{ + uint16_t day_of_year = dayOfyear(year, month, day); + return (day_of_year - 1) / 7 + 1; +} + +// 获取今天星期几 +uint8_t get_weekday(uint16_t year, uint8_t month, uint8_t day) +{ + uint8_t w = 0; + if (month == 1 || month == 2) + { + month += 12; + year--; + } + w = (day + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400) % 7; + return w + 1; +} + +// 传入十六进制0x23 返回十进制23 +uint8_t hex_format_dec(uint8_t hex) +{ + char buf[4]; + osel_memset((uint8_t *)buf, 0, 4); + sprintf(buf, "%x", hex); + int dec = 0; + int weight = 1; + int len = strlen(buf); + for (int i = len - 1; i >= 0; i--) + { + if (buf[i] >= '0' && buf[i] <= '9') + { + dec += (buf[i] - '0') * weight; + } + else if (buf[i] >= 'A' && buf[i] <= 'F') + { + dec += (buf[i] - 'A' + 10) * weight; + } + else if (buf[i] >= 'a' && buf[i] <= 'f') + { + dec += (buf[i] - 'a' + 10) * weight; + } + weight *= 10; + } + return dec; +} + +// 传入十进制23 返回十六进制0x23 +uint8_t dec_format_hex(uint8_t dec) +{ + char buf[4]; + osel_memset((uint8_t *)buf, 0, 4); + sprintf(buf, "%d", dec); + uint8_t hex = 0; + uint8_t len = strlen(buf); + for (uint8_t i = 0; i < len; i++) + { + char c = buf[i]; + if (c >= '0' && c <= '9') + { + hex = hex * 16 + (c - '0'); + } + else + { + continue; + } + } + return hex; +} + +/** + * @brief 北京时间转时间戳 + * @param {rtc_date_t} date + * @param {rtc_time_t} time + * @return {*} + * @note + */ +uint32_t time2stamp(rtc_date_t date, rtc_time_t time) +{ + uint32_t result; + uint16_t year = date.year + 2000; + result = (year - 1970) * 365 * 24 * 3600 + (_month_days[date.month - 1] + date.day - 1) * 24 * 3600 + (time.hour - 8) * 3600 + time.minute * 60 + time.second; + result += (date.month > 2 && (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) * 24 * 3600; // 闰月 + year -= 1969; + result += (year / 4 - year / 100 + year / 400) * 24 * 3600; // 闰年 + return result; +} + +/** + * @brief 时间戳转北京时间 + * @param {uint32_t} stamp + * @param {rtc_date_t} *date + * @param {rtc_time_t} *time + * @return {*} + * @note + */ +void stamp2time(uint32_t stamp, rtc_date_t *date, rtc_time_t *time) +{ + uint32_t days; + uint16_t leap_num; + + time->second = stamp % 60; + stamp /= 60; // 获取分 + time->minute = stamp % 60; + stamp += 8 * 60; + stamp /= 60; // 获取小时 + time->hour = stamp % 24; + days = stamp / 24; + leap_num = (days + 365) / 1461; + if (((days + 366) % 1461) == 0) + { + date->year = (days / 366) + 1970 - 2000; + date->month = 12; + date->day = 31; + } + else + { + days -= leap_num; + date->year = (days / 365) + 1970 - 2000; + days %= 365; + days += 1; + if (((date->year % 4) == 0) && (days == 60)) + { + date->month = 2; + date->day = 29; + } + else + { + if (((date->year % 4) == 0) && (days > 60)) + --days; + for (date->month = 0; _days[date->month] < days; date->month++) + { + days -= _days[date->month]; + } + ++date->month; + date->day = days; + } + } +} + +/**************************排序**************************/ +static void swap(uint16_t *a, uint16_t *b) +{ + uint16_t t = *a; + *a = *b; + *b = t; +} + +static int partition(uint16_t arr[], int low, int high) +{ + uint16_t pivot = arr[high]; + int i = (low - 1); + for (int j = low; j <= high - 1; j++) + { + if (arr[j] < pivot) + { + i++; + swap(&arr[i], &arr[j]); + } + } + swap(&arr[i + 1], &arr[high]); + return (i + 1); +} + +void quicksort(uint16_t arr[], int low, int high) +{ + if (low < high) + { + int pi = partition(arr, low, high); + quicksort(arr, low, pi - 1); + quicksort(arr, pi + 1, high); + } +} diff --git a/User/lib/src/malloc.c b/User/lib/src/malloc.c new file mode 100644 index 0000000..0acb00d --- /dev/null +++ b/User/lib/src/malloc.c @@ -0,0 +1,338 @@ +/* + * @Author: + * @Date: 2023-04-11 08:50:25 + * @LastEditors: xxx + * @LastEditTime: 2023-06-15 10:23:12 + * @Description: + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#include "../inc/data_type_def.h" +#include "../inc/malloc.h" + +/***************************************************************************** +* 科普C语言 * +****************************************************************************** +*__align 作用 :对齐跟数据在内存中的位置有关,也就是内存字节对齐。有点 +* 难理解,需要通过以下举例来理解 +*__attribute__作用:可以设置函数属性、变量属性和类型属性。在这里我们用来绝 +* 对定位地址,即专门指点内存地址 +* +*实例一: +* __align(32) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000))); +* 意思:定义一个数组,数组大小为MEM2_MAX_SIZE,数组所占的空间能被32整除,其数组 +* 的起始内存地址为0X68000000。 +* 如果MEM2_MAX_SIZE为2,则数组内存空间大小为32字节;如果MEM2_MAX_SIZE为33,则数 +* 组内存空间大小为64字节。 +* +*实例二: +struct A{ + char a; + unsigned int b; + unsigned char c; + char d; +}; + +另一个结构体是: +structB{ + char a; + unsigned int b; + unsigned char c; + char d; +}__attribute__((align(8))); + +sizeof(A) = 12(内存空间大小12个字节) +sizeof(B) = 8(内存空间大小8个字节) +********************************************************************************/ +// 内存池(32字节对齐) +// 可控制的内存大小 +__attribute__((aligned(32))) uint8_t mem1base[MEM1_MAX_SIZE]; // 内部SRAM内存池 +__attribute__((aligned(32))) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((section(".sram2"))); +// __attribute__((aligned(32))) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000))); // 外部SRAM内存池 +// 内存管理表 +// 可控制的内存控制块个数(每个内存块大小为32字节) +uint16_t mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; // 内部SRAM内存池MAP +uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE]; +// uint16_t mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000 + MEM2_MAX_SIZE))); // 外部SRAM内存池MAP + +// 内存管理参数 +// const 定义的变量的值是不允许改变的 +// 因为有内部SRAM和外部SRAM,所以用数组 +const uint32_t memtblsize[SRAMBANK] = {MEM1_ALLOC_TABLE_SIZE, MEM2_ALLOC_TABLE_SIZE}; // 内存表大小(即控制多少内存块) +const uint32_t memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE, MEM2_BLOCK_SIZE}; // 内存分块大小(一块内存块占多少字节内存空间) +const uint32_t memsize[SRAMBANK] = {MEM1_MAX_SIZE, MEM2_MAX_SIZE}; // 内存池大小(即可以分配的内存空间大小) + +// 内存管理控制器 +struct _m_mallco_dev mallco_dev = + { + my_mem_init, // 内存初始化 + my_mem_perused, // 内存使用率 + mem1base, mem2base, // 内存池 + mem1mapbase, mem2mapbase, // 内存管理状态表 + 0, 0, // 内存管理未就绪 +}; + +/******************************************* + *函数功能 :复制内存里面的数据(从一个内存空间里拷贝数据到另一内存空间里) + *函数名 :mymemcpy + *函数参数 :void *des void *src uint32_t n + *函数返回值:void + *描述 : + * *des :目标地址 + * *src :源地址 + * n :要复制的长度(字节为单位) + *********************************************/ +void mymemcpy(void *des, void *src, uint32_t n) +{ + // 一般我们不会对要操作的参数指针进行操作 + // 而是通过一个变量指针作为中介,这样是为了出于安全保证 + uint8_t *xdes = des; + uint8_t *xsrc = src; + // 变量在++之前,则先用,后++ + // 变量在++之后,先++,后使用 + while (n--) + *xdes++ = *xsrc++; +} + +/***************************************************** + *函数功能 :设置内存(设置内存空间的值,一般用来对空间清0) + *函数名 :mymemset + *函数参数 :void *s uint8_t c uint32_t count + *函数返回值:void + *描述 : + * *s :内存首地址 + * c :要设置的值 + * count :需要设置的内存大小(字节为单位) + ******************************************************/ +void mymemset(void *s, uint8_t c, uint32_t count) +{ + // 一般我们不会对要操作的参数指针进行操作 + // 而是通过一个变量指针作为中介,这样是为了出于安全保证 + uint8_t *xs = s; + // 变量在++之前,则先用,后++ + // 变量在++之后,先++,后使用 + while (count--) + *xs++ = c; +} + +/***************************************************************** + *函数功能 :内存管理初始化 + *函数名 :my_mem_init + *函数参数 :uint8_t memx + *函数返回值:void + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * + * 其实所谓的初始化就是把内存池和内存表(他们的本质就是数组)清0 + ******************************************************************/ +void my_mem_init(uint8_t memx) +{ + mymemset(mallco_dev.memmap[memx], 0, memtblsize[memx] * 2); // 内存状态表数据清零 + mymemset(mallco_dev.membase[memx], 0, memsize[memx]); // 内存池所有数据清零 + mallco_dev.memrdy[memx] = 1; // 内存管理初始化OK,即内存池和内存表都清0了 +} + +/***************************************************************** + *函数功能 :获取内存使用率 + *函数名 :my_mem_perused + *函数参数 :uint8_t memx + *函数返回值:void + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * + * 是否占用是通过判断mem1mapbase或mem2mapbase的数组成员是否非0,如果 + * 非0则被占用,之中数组成员值有一定意义,代表占了多少块,如值为10,则表示 + * 该申请了连续10个内存块 + ******************************************************************/ +uint8_t my_mem_perused(uint8_t memx) +{ + uint32_t used = 0; + uint32_t i; + // memtblsize:内存表大小(一共内存块数) + // 遍历内存表数组 + for (i = 0; i < memtblsize[memx]; i++) + { + // mallco_dev.memmap[memx]:内存表数组 + // 取出每个成员判断是否非0 + // 非0则是用了 + if (mallco_dev.memmap[memx][i]) + used++; + } + + // 使用数量/数量总数*100 = 使用率 + return (used * 100) / (memtblsize[memx]); +} + +/***************************************************************** + *函数功能 :内存分配(内部调用)------确定在内存池的偏移量 + *函数名 :my_mem_malloc + *函数参数 :uint8_t memx,uint32_t size + *函数返回值:uint32_t + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * size:要分配的内存大小(字节) + * 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 + * + * 注意:内存表的遍历是从后往前的 + ******************************************************************/ +uint32_t my_mem_malloc(uint8_t memx, uint32_t size) +{ + signed long offset = 0; // 偏移量变量 + uint32_t nmemb; // 需要的内存块数 + uint32_t cmemb = 0; // 连续空内存块数,保证我们申请的内存块是连续的 + uint32_t i; + // 判断是否已执行了初始化 + if (!mallco_dev.memrdy[memx]) + mallco_dev.init(memx); // 未初始化,先执行初始化 + if (size == 0) + return 0XFFFFFFFF; // 不需要分配 + // 内存块数 = 申请空间大小(字节单位) / t一个内存块大小(字节单位) + nmemb = size / memblksize[memx]; // 获取需要分配的连续内存块数 + // 申请空间大小(字节单位) / t一个内存块大小(字节单位) != 0 + // 如果非0则要多申请一块内存块 + if (size % memblksize[memx]) + nmemb++; + // 内存表的遍历是从后往前的 + for (offset = memtblsize[memx] - 1; offset >= 0; offset--) // 搜索整个内存控制区 + { + // 判断该内存块是否被占用了 + if (!mallco_dev.memmap[memx][offset]) + cmemb++; // 连续空内存块数增加 + // 保证内存块的连续性 + else + cmemb = 0; // 连续内存块清零 + // 确定好所有内存块位置后 + if (cmemb == nmemb) // 找到了连续nmemb个空内存块 + { + for (i = 0; i < nmemb; i++) // 标注内存块非空 + { + // 开始往内存块在内存表数组的位置标记该内存块被占用 + mallco_dev.memmap[memx][offset + i] = nmemb; + } + + // 确定申请空间在内存池数组位置 在内存表数组位置*一个内存块大小(32字节) + return (offset * memblksize[memx]); // 返回偏移地址 + } + } + return 0XFFFFFFFF; // 未找到符合分配条件的内存块 +} + +/***************************************************************** + *函数功能 :释放内存(内部调用)------内存池偏移量清除申请空间在内存表的占用标志 + *函数名 :my_mem_free + *函数参数 :uint8_t memx,uint32_t offset + *函数返回值:uint32_t + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * size:内存地址偏移(字节)--------也就是在内存池数组的位置 + * 返回值:0,释放成功;1,释放失败; + * + ******************************************************************/ +uint8_t my_mem_free(uint8_t memx, uint32_t offset) +{ + int i; + int index; + int nmemb; + + // 判断是否初始化 + if (!mallco_dev.memrdy[memx]) // 未初始化,先执行初始化 + { + mallco_dev.init(memx); + return 1; // 未初始化 + } + + // 判断这个偏移量是否超出了内存池的大小 + if (offset < memsize[memx]) // 偏移在内存池内. + { + // 内存表偏移量 = 内存池偏移量/一块内存块大小 + index = offset / memblksize[memx]; // 偏移所在内存块号码 + // 内存表数组成员的值就是申请的块数 + nmemb = mallco_dev.memmap[memx][index]; // 内存块数量 + + for (i = 0; i < nmemb; i++) // 内存块清零 + { + // 清除申请空间在内存表的标记 + mallco_dev.memmap[memx][index + i] = 0; + } + return 0; + } + else + return 1; // 偏移超区了. +} + +/***************************************************************** + *函数功能 :分配内存(外部调用) + *函数名 :mymalloc + *函数参数 :uint8_t memx,uint32_t size + *函数返回值:void * + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * size:内存大小(字节) + * 返回值:分配到的内存首地址 + ******************************************************************/ +void *mymalloc(uint8_t memx, uint32_t size) +{ + uint32_t offset; // 在内存池数组的偏移量变量 + // 获取在内存池数组的偏移量 + offset = my_mem_malloc(memx, size); + // 如果申请错误,则返回空地址 + if (offset == 0XFFFFFFFF) + return NULL; + // 如果申请成功,则返回申请空间首地址 + else + return (void *)((uint32_t)mallco_dev.membase[memx] + offset); +} + +/***************************************************************** + *函数功能 :释放内存(外部调用) + *函数名 :myfree + *函数参数 :uint8_t memx,void *ptr + *函数返回值:uint32_t + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * ptr :要释放的内存空间首地址 + ******************************************************************/ +void myfree(uint8_t memx, void *ptr) +{ + uint32_t offset; + uint32_t n; // 该要释放的空间的空间大小 + if (ptr == NULL) + return; // 地址为0. + // 确定申请空间的内存池偏移量 + offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase[memx]; + // 空间占内存池空间的大小 + n = mallco_dev.memmap[memx][offset / memblksize[memx]] * memblksize[memx]; + // 释放内存池对应空间的数据 + mymemset(ptr, 0, n); + // 释放内存表 + my_mem_free(memx, offset); // 释放内存 +} + +/***************************************************************** + *函数功能 :重新分配内存(外部调用) + *函数名 :myfree + *函数参数 :uint8_t memx,void *ptr + *函数返回值:uint32_t + *描述 : + * memx:所属内存块,即是内部SRAM还是外部SRAM的内存块 + * ptr :旧内存空间地址首地址 + * size:要重新分配的内存大小(字节) + ******************************************************************/ +void *myrealloc(uint8_t memx, void *ptr, uint32_t size) +{ + uint32_t offset; + + // 申请一个新的空间 + offset = my_mem_malloc(memx, size); + if (offset == 0XFFFFFFFF) + return NULL; + else + { + // 把旧空间的数据复制到新空间里 + mymemcpy((void *)((uint32_t)mallco_dev.membase[memx] + offset), ptr, size); // 拷贝旧内存内容到新内存 + // 删掉旧空间 + myfree(memx, ptr); // 释放旧内存 + // 返回新空间地址 + return (void *)((uint32_t)mallco_dev.membase[memx] + offset); // 返回新内存首地址 + } +} diff --git a/User/lib/src/mlist.c b/User/lib/src/mlist.c new file mode 100644 index 0000000..38db5e4 --- /dev/null +++ b/User/lib/src/mlist.c @@ -0,0 +1,149 @@ +/* + * @Author: + * @Date: 2023-04-04 08:39:23 + * @LastEditors: xxx + * @LastEditTime: 2023-04-21 12:08:31 + * @Description: + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "../inc/mlist.h" + +#ifndef NULL +#define NULL ((void *)0) +#endif + +void list_init(list_head_t *const ptr) +{ + (ptr)->next = (ptr); + (ptr)->prev = (ptr); +} + +/* + * 在两个连续的链表元素中插入一个新的元素 + */ +static void __list_add(list_head_t *const new_entry, + list_head_t *const prev, + list_head_t *const next) +{ + next->prev = new_entry; + new_entry->next = next; + new_entry->prev = prev; + prev->next = new_entry; +} + +/** + * 在指定的位置之前插入一个元素 + */ +void list_insert_forwards(list_head_t *const new_entry, list_head_t *const pos) +{ + __list_add(new_entry, pos->prev, pos); +} + +/** + * 在指定的位置之后插入一个元素 + */ +void list_insert_backwards(list_head_t *const new_entry, list_head_t *const pos) +{ + __list_add(new_entry, pos, pos->next); +} + +/** + * 在链表尾部插入新的元素 + */ +void list_add_to_tail(list_head_t *const new_entry, list_head_t *const list) +{ + __list_add(new_entry, list->prev, list); +} + +/** + * 在链表头后插入新的元素 + */ +void list_add_to_head(list_head_t *const new_entry, list_head_t *const list) +{ + __list_add(new_entry, list, list->next); +} + +static void __list_del(list_head_t *const prev, list_head_t *const next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * 删除指定的链表元素 + */ +void list_del(list_head_t *const elem) +{ + __list_del(elem->prev, elem->next); + elem->next = (list_head_t *)NULL; + elem->prev = (list_head_t *)NULL; +} + +/* + * 删除并返回链表尾元素 + */ +list_head_t *list_curtail(const list_head_t *const head) +{ + list_head_t *tail = head->prev; + list_del(tail); + return tail; +} + +/** + * 判断链表是否为空 + */ +bool list_empty(const list_head_t *const head) +{ + return (((head)->next == head) || (head->next == NULL)); +} + +/** + * 获取链表第一个元素 + */ +list_head_t *list_first_elem_look(const list_head_t *const head) +{ + if (!list_empty(head)) + { + return head->next; + } + return NULL; +} + +/** + * 从制定位置后取出并删除该元素 + */ +list_head_t *list_next_elem_get(const list_head_t *const pos) +{ + if (pos == NULL) + { + return NULL; + } + + list_head_t *temp = (pos)->next; + if (temp != NULL) + { + list_del(temp); + } + + return temp; +} + +/** + * 将链表元素从一个队列移出,再添加到另外一个队列中 + */ +void list_move_to_another_head(list_head_t *const elem, list_head_t *const head) +{ + __list_del(elem->prev, elem->next); + list_add_to_head(elem, head); +} + +/** + * 将元素从一个队列中取出,然后再放入另外一个队列的尾部; + */ +void list_move_to_another_tail(list_head_t *const elem, list_head_t *const head) +{ + __list_del(elem->prev, elem->next); + list_add_to_tail(elem, head); +} diff --git a/User/lib/src/pbuf.c b/User/lib/src/pbuf.c new file mode 100644 index 0000000..3b02e59 --- /dev/null +++ b/User/lib/src/pbuf.c @@ -0,0 +1,401 @@ +/* + * pbuf.c + * + * Created on: 2022年12月5日 + * Author: xushenghao + */ +#include "../inc/debug.h" +#include "../inc/pbuf.h" +#include "../inc/osel_arch.h" +#define PBUF_DATA_SIZE(pbuf) (pbuf->end - pbuf->head) + +typedef struct _pbuf_type_t +{ + uint8_t type; + uint16_t size; + uint8_t num; +} pbuf_type_t; + +static list_head_t pbuf_freez_blocks[PBUF_TYPE_MAX_NUM]; +uint8_t pbuf_cnt[PBUF_TYPE_MAX_NUM] = {0}; + +#if PBUF_DBG_EN > 0 +static pbuf_t *pbuf_used_p[PBUF_TYPE_MAX_NUM][PBUF_NUM_MAX]; +#endif + +static void poly_type_pbuf_init(uint8_t type, uint16_t pkt_len, uint8_t num) +{ + void *mem = NULL; + pbuf_t *pbuf = NULL; + + list_init(&pbuf_freez_blocks[type]); + + if (num == 0) + { + return; + } + + mem = osel_mem_alloc((sizeof(pbuf_t) + pkt_len) * num); + DBG_ASSERT(mem != NULL __DBG_LINE); + + for (uint8_t i = 0; i < num; i++) + { + pbuf = (pbuf_t *)((uint8_t *)mem + i * (sizeof(pbuf_t) + pkt_len)); + pbuf->head = (uint8_t *)pbuf + sizeof(pbuf_t); + pbuf->end = (uint8_t *)pbuf + sizeof(pbuf_t) + pkt_len; + pbuf->data_p = pbuf->head; + list_add_to_head(&pbuf->list, &pbuf_freez_blocks[type]); + } + + pbuf_cnt[type] = num; +} + +void pbuf_initz(void) +{ + poly_type_pbuf_init(SMALL_PBUF, + SMALL_PBUF_BUFFER_SIZE, + SMALL_PBUF_NUM); + + poly_type_pbuf_init(MEDIUM_PBUF, + MEDIUM_PBUF_BUFFER_SIZE, + MEDIUM_PBUF_NUM); + + poly_type_pbuf_init(LARGE_PBUF, + LARGE_PBUF_BUFFER_SIZE, + LARGE_PBUF_NUM); +} + +static pbuf_type_t search_free_pbuf(uint8_t pbuf_type) +{ + pbuf_type_t free_pbuf_temp; + + switch (pbuf_type) + { // 没有break让代码顺序执行 + case SMALL_PBUF: + if (!list_empty(&pbuf_freez_blocks[SMALL_PBUF])) + { + free_pbuf_temp.type = SMALL_PBUF; + free_pbuf_temp.size = SMALL_PBUF_BUFFER_SIZE; + free_pbuf_temp.num = SMALL_PBUF_NUM; + } + break; + case MEDIUM_PBUF: + if (!list_empty(&pbuf_freez_blocks[MEDIUM_PBUF])) + { + free_pbuf_temp.type = MEDIUM_PBUF; + free_pbuf_temp.size = MEDIUM_PBUF_BUFFER_SIZE; + free_pbuf_temp.num = MEDIUM_PBUF_NUM; + } + break; + case LARGE_PBUF: + if (!list_empty(&pbuf_freez_blocks[LARGE_PBUF])) + { + free_pbuf_temp.type = LARGE_PBUF; + free_pbuf_temp.size = LARGE_PBUF_BUFFER_SIZE; + free_pbuf_temp.num = LARGE_PBUF_NUM; + } + break; + default: + free_pbuf_temp.type = PBUF_TYPE_INVALID; + } + return free_pbuf_temp; +} + +static pbuf_type_t pbuf_type_select(uint16_t size) +{ + pbuf_type_t free_pbuf; + if (size <= SMALL_PBUF_BUFFER_SIZE) + { + free_pbuf = search_free_pbuf(SMALL_PBUF); + } + else if ((size > SMALL_PBUF_BUFFER_SIZE) && (size <= MEDIUM_PBUF_BUFFER_SIZE)) + { + free_pbuf = search_free_pbuf(MEDIUM_PBUF); + } + else if ((size > MEDIUM_PBUF_BUFFER_SIZE) && (size <= LARGE_PBUF_BUFFER_SIZE)) + { + free_pbuf = search_free_pbuf(LARGE_PBUF); + } + else + { + DBG_ASSERT(false __DBG_LINE); + } + + if (free_pbuf.type == PBUF_TYPE_INVALID) + { + // DBG_ASSERT(false __DBG_LINE); + } + + return free_pbuf; +} + +#if PBUF_DBG_EN > 0 +static void add_to_pbuf_used_ptr(pbuf_t *pbuf, pbuf_type_t pbuf_type) +{ + hal_int_state_t s; + HAL_ENTER_CRITICAL(s); + for (uint8_t i = 0; i < PBUF_NUM_MAX; i++) + { + if (pbuf_used_p[pbuf_type.type][i] == NULL) + { + pbuf_used_p[pbuf_type.type][i] = pbuf; + break; + } + } + HAL_EXIT_CRITICAL(s); +} +#endif + +pbuf_t *pbuf_allocz(uint16_t size _PLINE1_) +{ + + pbuf_type_t avilable_pbuf_type; + pbuf_t *pbuf = NULL; + hal_int_state_t s; + HAL_ENTER_CRITICAL(s); + avilable_pbuf_type = pbuf_type_select(size); + if (avilable_pbuf_type.type == PBUF_TYPE_INVALID) + { + return NULL; + } + pbuf = list_entry_decap(&pbuf_freez_blocks[avilable_pbuf_type.type], + pbuf_t, + list); + pbuf_cnt[avilable_pbuf_type.type]--; + HAL_EXIT_CRITICAL(s); + + DBG_ASSERT(pbuf != NULL __DBG_LINE); + if (pbuf == NULL) + { + return NULL; + } + + osel_memset(pbuf->head, 0, avilable_pbuf_type.size); + osel_memset((uint8_t *)&pbuf->attri, 0, sizeof(pbuf->attri)); + + HAL_ENTER_CRITICAL(s); + pbuf->used = true; + pbuf->data_len = 0; + pbuf->data_p = pbuf->head; + list_init(&pbuf->list); + HAL_EXIT_CRITICAL(s); + +#if PBUF_DBG_EN > 0 + pbuf->alloc_line = line; + pbuf->free_line = 0; + add_to_pbuf_used_ptr(pbuf, avilable_pbuf_type); +#endif + return pbuf; +} + +static pbuf_type_t get_pbuf_type(pbuf_t **pbuf) +{ + pbuf_type_t current_pbuf_type; + uint16_t size_temp; + + DBG_ASSERT(*pbuf != NULL __DBG_LINE); + DBG_ASSERT(pbuf != NULL __DBG_LINE); + + size_temp = (*pbuf)->end - (*pbuf)->head; + + if (size_temp == SMALL_PBUF_BUFFER_SIZE) + { + current_pbuf_type.type = SMALL_PBUF; + current_pbuf_type.size = SMALL_PBUF_BUFFER_SIZE; + current_pbuf_type.num = SMALL_PBUF_NUM; + } + + else if (size_temp == MEDIUM_PBUF_BUFFER_SIZE) + { + current_pbuf_type.type = MEDIUM_PBUF; + current_pbuf_type.size = MEDIUM_PBUF_BUFFER_SIZE; + current_pbuf_type.num = MEDIUM_PBUF_NUM; + } + + else if (size_temp == LARGE_PBUF_BUFFER_SIZE) + { + current_pbuf_type.type = LARGE_PBUF; + current_pbuf_type.size = LARGE_PBUF_BUFFER_SIZE; + current_pbuf_type.num = LARGE_PBUF_NUM; + } + else + { + DBG_ASSERT(false __DBG_LINE); + } + + return current_pbuf_type; +} + +#if PBUF_DBG_EN > 0 +static void delete_from_pbuf_used_ptr(pbuf_t **pbuf, pbuf_type_t pbuf_type_temp) +{ + hal_int_state_t s; + HAL_ENTER_CRITICAL(s); + + for (uint8_t i = 0; i < PBUF_NUM_MAX; i++) + { + if (pbuf_used_p[pbuf_type_temp.type][i] == *pbuf) + { + pbuf_used_p[pbuf_type_temp.type][i] = NULL; + break; + } + } + + HAL_EXIT_CRITICAL(s); +} +#endif + +void pbuf_freez(pbuf_t **const pbuf _PLINE2_) +{ + + pbuf_type_t pbuf_type; + hal_int_state_t s; + DBG_ASSERT(*pbuf != NULL __DBG_LINE); + DBG_ASSERT(pbuf != NULL __DBG_LINE); + DBG_ASSERT((*pbuf)->used == true __DBG_LINE); // 用于检测嵌套的重复释放 + + if (pbuf == NULL || *pbuf == NULL || (*pbuf)->used == false) + { + return; + } + + pbuf_type = get_pbuf_type(pbuf); + +#if PBUF_DBG_EN > 0 + delete_from_pbuf_used_ptr(pbuf, pbuf_type); + (*pbuf)->free_line = line; +#endif + osel_memset((*pbuf)->head, 0, pbuf_type.size); + osel_memset((uint8_t *)&((*pbuf)->attri), 0, sizeof((*pbuf)->attri)); + + HAL_ENTER_CRITICAL(s); + + if ((*pbuf)->data_len > ((*pbuf)->end - (*pbuf)->head)) + { + DBG_ASSERT(false __DBG_LINE); + } + + (*pbuf)->used = false; + (*pbuf)->data_len = 0; + (*pbuf)->data_p = (*pbuf)->head; + list_init(&(*pbuf)->list); + + list_add_to_tail(&(*pbuf)->list, &pbuf_freez_blocks[pbuf_type.type]); + +#if PBUF_DBG_EN > 0 + uint8_t list_cnt = 0; + list_count(&pbuf_freez_blocks[pbuf_type.type], list_cnt); + DBG_ASSERT(list_cnt != 0 __DBG_LINE); +#endif + + pbuf_cnt[pbuf_type.type]++; + +#if PBUF_DBG_EN > 0 + (*pbuf)->alloc_line = 0; +#endif + + HAL_EXIT_CRITICAL(s); + + *pbuf = NULL; +} + +uint8_t *pbuf_skip_datap_forward(pbuf_t *const pbuf, uint8_t len) +{ + uint8_t *datap_tmp = NULL; + hal_int_state_t s; + DBG_ASSERT(pbuf != NULL __DBG_LINE); + if (pbuf == NULL) + { + return NULL; + } + + HAL_ENTER_CRITICAL(s); + + if ((pbuf->data_p + len) > pbuf->end) + { + HAL_EXIT_CRITICAL(s); + return NULL; + } + + pbuf->data_p += len; + datap_tmp = pbuf->data_p; + + HAL_EXIT_CRITICAL(s); + return datap_tmp; +} + +uint8_t *pbuf_skip_datap_backward(pbuf_t *const pbuf, uint8_t len) +{ + uint8_t *datap_tmp = NULL; + hal_int_state_t s; + DBG_ASSERT(pbuf != NULL __DBG_LINE); + if (pbuf == NULL) + { + return NULL; + } + + HAL_ENTER_CRITICAL(s); + + if ((pbuf->data_p - len) < pbuf->head) + { + HAL_EXIT_CRITICAL(s); + return NULL; + } + + pbuf->data_p -= len; + datap_tmp = pbuf->data_p; + + HAL_EXIT_CRITICAL(s); + return datap_tmp; +} + +bool pbuf_copy_data_in(pbuf_t *const pbuf, const uint8_t *const src, uint8_t len) +{ + DBG_ASSERT(pbuf != NULL __DBG_LINE); + if (pbuf == NULL) + { + return false; + } + hal_int_state_t s; + HAL_ENTER_CRITICAL(s); + + if ((pbuf->data_p + len) > pbuf->end) + { + HAL_EXIT_CRITICAL(s); + return false; + } + else + { + osel_memcpy(pbuf->data_p, src, len); + pbuf->data_p += len; + pbuf->data_len += len; + + HAL_EXIT_CRITICAL(s); + return true; + } +} + +bool pbuf_copy_data_out(uint8_t *const dst, pbuf_t *const pbuf, uint8_t len) +{ + DBG_ASSERT(pbuf != NULL __DBG_LINE); + if (pbuf == NULL) + { + return false; + } + hal_int_state_t s; + HAL_ENTER_CRITICAL(s); + + if ((pbuf->data_p + len) > pbuf->end) + { + HAL_EXIT_CRITICAL(s); + return false; + } + else + { + osel_memcpy(dst, pbuf->data_p, len); + pbuf->data_p += len; + + HAL_EXIT_CRITICAL(s); + return true; + } +} diff --git a/User/lib/src/sqqueue.c b/User/lib/src/sqqueue.c new file mode 100644 index 0000000..a3eb614 --- /dev/null +++ b/User/lib/src/sqqueue.c @@ -0,0 +1,410 @@ +/** + * @file sqqueue.c + * @author xxx + * @date 2023-06-25 13:07:02 + * @brief 提供循环队列功能 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "../inc/sqqueue.h" +#include "../inc/osel_arch.h" + +#define SQQ_ENTRY_SIZE (queue_ptr->entry_size) +#define SQQ_LEN (queue_ptr->sqq_len) + +/** + * @brief 初始化队列控制结构体 + * @param p_this 队列控制结构体的指针 + * @param entry_size 队列中每个元素的大小 + * @param sqq_len 队列的最大长度 + * @return {bool} 初始化成功返回true,否则返回false + * @note 此函数用于初始化队列控制结构体,确保队列有足够的空间存储元素 + */ +static bool sqqueue_init(sqqueue_ctrl_t *const p_this, + uint8_t entry_size, + uint16_t sqq_len) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + sqqueue_t *queue_ptr = &(p_this->sqq); + + if (p_this != NULL) + { + queue_ptr->entry_size = entry_size; + queue_ptr->sqq_len = sqq_len + 1; + queue_ptr->base = (uint8_t *)osel_mem_alloc(SQQ_LEN * SQQ_ENTRY_SIZE); + if (queue_ptr->base == NULL) + { + return false; + } + queue_ptr->front = 0; + queue_ptr->rear = 0; + + return true; + } + + return false; +} + +/** + * @brief 获取队列的长度 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @return {uint16_t} 队列的长度 + * @note 此函数用于获取队列的长度,包括队列中元素的数量和最大长度 + */ +static uint16_t sqqueue_length(const sqqueue_ctrl_t *const p_this) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + const sqqueue_t *const queue_ptr = &(p_this->sqq); + uint16_t length = 0; + if (p_this != NULL) + { + length = (queue_ptr->rear + SQQ_LEN - queue_ptr->front); + + if (length >= SQQ_LEN) + { + length -= SQQ_LEN; + } + } + + return length; +} + +/** + * @brief 获取队列的长度 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @return {uint16_t} 队列的长度 + * @note 此函数用于获取队列的长度,包括队列中元素的数量和最大长度 + */ +static bool sqqueue_full(const sqqueue_ctrl_t *const p_this) +{ + uint16_t rear = 0; + + DBG_ASSERT(p_this != NULL __DBG_LINE); + + if (p_this != NULL) + { + const sqqueue_t *const queue_ptr = &(p_this->sqq); + rear = queue_ptr->rear + 1; + if (rear >= SQQ_LEN) + { + rear -= SQQ_LEN; + } + if (rear == queue_ptr->front) + { + return true; + } + } + + return false; +} + +/** + * @brief 将元素添加到队列中 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @param {void} *e 要添加的元素 + * @return {bool} 添加成功返回true,否则返回false + * @note 此函数用于将元素添加到队列中,确保队列有足够的空间存储元素 + */ +static bool enter_sqqueue(sqqueue_ctrl_t *const p_this, const void *const e) +{ + uint16_t rear = 0; + sqqueue_t *queue_ptr = &(p_this->sqq); + + if ((p_this != NULL) && (e != NULL)) + { + rear = queue_ptr->rear + 1; + if (rear >= SQQ_LEN) + { + rear -= SQQ_LEN; + } + + if (rear == queue_ptr->front) + { + return false; + } + + /* 根据e的长度进行内存拷贝 */ + DBG_ASSERT(queue_ptr->rear != SQQ_LEN __DBG_LINE); + osel_memcpy(queue_ptr->base + (queue_ptr->rear * SQQ_ENTRY_SIZE), + e, + SQQ_ENTRY_SIZE); + queue_ptr->rear = rear; + + return true; + } + return false; +} + +/** + * @brief 将字符串添加到队列中 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @param {const void} *string 要添加的字符串 + * @param {uint16_t} cnt 要添加的字符串的长度 + * @return {bool} 添加成功返回true,否则返回false + * @note 此函数用于将字符串添加到队列中,确保队列有足够的空间存储字符串 + */ +static bool string_enter_sqqueue(sqqueue_ctrl_t *const p_this, + const void *const string, + uint16_t cnt) +{ + uint16_t rear = 0; + uint16_t length = 0; + sqqueue_t *queue_ptr = &(p_this->sqq); + + if ((p_this != NULL) && (string != NULL)) + { + /* 判断是否超出队列长度 */ + length = sqqueue_length(p_this); // 已有元素个数 + if (length == 0xFFFF) + { + return false; + } + + length = (SQQ_LEN - 1) - length; // 可写入个数 + if (length < cnt) + { + return false; + } + + rear = queue_ptr->rear + cnt; + if (rear >= SQQ_LEN) + { + rear -= SQQ_LEN; + uint8_t half = SQQ_LEN - queue_ptr->rear; + osel_memcpy(queue_ptr->base + (queue_ptr->rear * SQQ_ENTRY_SIZE), + string, half * SQQ_ENTRY_SIZE); + uint8_t *half_p = (uint8_t *)string; + osel_memcpy(queue_ptr->base, (uint8_t *)&half_p[half], rear * SQQ_ENTRY_SIZE); + } + else + { + osel_memcpy(queue_ptr->base + (queue_ptr->rear * SQQ_ENTRY_SIZE), + string, SQQ_ENTRY_SIZE * cnt); + } + + queue_ptr->rear = rear; + + return true; + } + return false; +} + +/** + * @brief 从队列中删除元素 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @return {void *} 删除的元素,如果队列为空则返回NULL + * @note 此函数用于从队列中删除元素,确保队列中有足够的空间存储元素 + */ +static void *delete_sqqueue(sqqueue_ctrl_t *const p_this) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + uint16_t front = 0; + + sqqueue_t *queue_ptr = NULL; + + if (p_this != NULL) + { + void *p_elem = NULL; + queue_ptr = &(p_this->sqq); + if (queue_ptr->rear == queue_ptr->front) + { + return NULL; + } + /* 根据元素类型大小计算出偏移量,得到该元素首地址 */ + p_elem = (void *)((queue_ptr->base) + (queue_ptr->front * SQQ_ENTRY_SIZE)); + front = queue_ptr->front + 1; + if (front >= SQQ_LEN) + { + front -= SQQ_LEN; + } + queue_ptr->front = front; + + return p_elem; + } + return NULL; +} + +/** + * @brief 撤销队列中的一个元素 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @return {*} 返回被撤销的元素,如果队列为空则返回NULL + * @note + */ +static void *revoke_sqqueue(sqqueue_ctrl_t *const p_this) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + uint16_t rear = 0; + sqqueue_t *queue_ptr = NULL; + + if (p_this != NULL) + { + void *p_elem = NULL; + + queue_ptr = &(p_this->sqq); + if (queue_ptr->rear == queue_ptr->front) + { + return NULL; + } + + rear = queue_ptr->rear; + if (rear == 0) + { + rear = SQQ_LEN - 1; + } + else + { + rear--; + } + queue_ptr->rear = rear; + /* 根据元素类型大小计算出偏移量,得到该元素首地址*/ + p_elem = (void *)((queue_ptr->base) + (queue_ptr->rear * SQQ_ENTRY_SIZE)); + + return p_elem; + } + return NULL; +} + +/** + * @brief 清空队列 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @return {void} + * @note + */ +static void clear_sqq(sqqueue_ctrl_t *const p_this) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + + sqqueue_t *queue_ptr = &(p_this->sqq); + if (p_this != NULL) + { + queue_ptr->front = 0; + queue_ptr->rear = 0; + } +} + +/** + * @brief 遍历队列 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @param {void (*)(const void *e)} vi 遍历函数,参数为队列中的一个元素 + * @return {void} + * @note + */ +static void traverse(sqqueue_ctrl_t *const p_this, void (*vi)(const void *e)) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + sqqueue_t *queue_ptr = NULL; + uint16_t i = 0; + + if (p_this != NULL) + { + queue_ptr = &(p_this->sqq); + + if (queue_ptr->rear == queue_ptr->front) + { + return; + } + + i = queue_ptr->front; + while (i != queue_ptr->rear) + { + vi((void *)((queue_ptr->base) + (i * SQQ_ENTRY_SIZE))); + if (++i >= SQQ_LEN) + { + i = 0; + } + } + } +} + +/** + * @brief 从队列中删除一个元素 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @param {uint16_t} offset_to_front 要删除的元素在队列中的偏移量,从队头开始 + * @return {void} + * @note + */ +static void qremove(sqqueue_ctrl_t *const p_this, uint16_t offset_to_front) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + sqqueue_t *queue_ptr = NULL; + uint16_t i = 0; + + if (p_this != NULL) + { + queue_ptr = &(p_this->sqq); + DBG_ASSERT(offset_to_front < SQQ_LEN __DBG_LINE); + + if (queue_ptr->rear == queue_ptr->front) + { + return; + } + + uint16_t j = 0; + + for (i = offset_to_front; i > 0; i--) + { + /* 定位待删除元素在队列中的位置 */ + j = queue_ptr->front + i; + + if (j >= SQQ_LEN) + { + j -= SQQ_LEN; + } + + if (j == 0) // 在翻转位置特殊处理拷贝的源地址 + { + osel_memcpy(queue_ptr->base + (0 * SQQ_ENTRY_SIZE), + queue_ptr->base + ((SQQ_LEN - 1) * SQQ_ENTRY_SIZE), + SQQ_ENTRY_SIZE); + } + else + { + osel_memcpy(queue_ptr->base + (j * SQQ_ENTRY_SIZE), + queue_ptr->base + ((j - 1) * SQQ_ENTRY_SIZE), + SQQ_ENTRY_SIZE); + } + } + + /* 减少队列长度 */ + uint16_t front = queue_ptr->front + 1; + if (front >= SQQ_LEN) + { + front -= SQQ_LEN; + } + + queue_ptr->front = front; + } +} + +/** + * @brief 初始化队列控制结构体 + * @param {sqqueue_ctrl_t} *p_this 队列控制结构体的指针 + * @param {uint8_t} entry_size 队列中每个元素的类型大小 + * @param {uint16_t} sqq_len 队列的最大长度 + * @return {bool} 初始化成功返回true,否则返回false + * @note + */ +bool sqqueue_ctrl_init(sqqueue_ctrl_t *const p_this, + uint8_t entry_size, + uint16_t sqq_len) +{ + DBG_ASSERT(p_this != NULL __DBG_LINE); + + if (p_this != NULL) + { + if (sqqueue_init(p_this, entry_size, sqq_len) != false) + { + p_this->enter = enter_sqqueue; + p_this->string_enter = string_enter_sqqueue; + p_this->del = delete_sqqueue; + p_this->revoke = revoke_sqqueue; + p_this->get_len = sqqueue_length; + p_this->full = sqqueue_full; + p_this->clear_sqq = clear_sqq; + p_this->traverse = traverse; + p_this->remove = qremove; + return true; + } + } + return false; +} diff --git a/User/lib/unity/unity.c b/User/lib/unity/unity.c new file mode 100644 index 0000000..be6ae2e --- /dev/null +++ b/User/lib/unity/unity.c @@ -0,0 +1,2582 @@ +/* ========================================================================= + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL \ + do \ + { \ + Unity.CurrentTestFailed = 1; \ + UNITY_OUTPUT_FLUSH(); \ + TEST_ABORT(); \ + }while (0) +#define UNITY_IGNORE_AND_BAIL \ + do \ + { \ + Unity.CurrentTestIgnored = 1; \ + UNITY_OUTPUT_FLUSH(); \ + TEST_ABORT(); \ + } while (0) +#define RETURN_IF_FAIL_OR_IGNORE \ + do \ + { \ + if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) \ + { \ + TEST_ABORT(); \ + } \ + } while (0) + + struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char *pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char *string) +{ + const char *pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char *string) +{ + const char *pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char *string, const UNITY_UINT32 length) +{ + const char *pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (isnan(number)) + { + UnityPrint("nan"); + } + else if (isinf(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) + { + number *= 1e10f; + exponent -= 10; + } + while (number * factor < (UNITY_DOUBLE)min_scaled) + { + factor *= 10.0f; + exponent--; + } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) + { + number /= 1e10f; + exponent += 10; + } + while (number / divisor > (UNITY_DOUBLE)max_scaled) + { + divisor *= 10.0f; + exponent++; + } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) + { + n_int *= 10; + factor *= 10.0f; + exponent--; + } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char *file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char *msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char *expected, const char *actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char *expected, + const char *actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char *msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) + { + return 0; + } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) + { + return; + } + if ((threshold == actual)) + { + failed = 1; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) + { + failed = 1; + } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) + { + failed = 1; + } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) + { + failed = 1; + } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) + { + failed = 1; + } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) + { + UnityPrint(UnityStrGt); + } + if (compare & UNITY_SMALLER_THAN) + { + UnityPrint(UnityStrLt); + } + if (compare & UNITY_EQUAL_TO) + { + UnityPrint(UnityStrOrEqual); + } + if (compare == UNITY_NOT_EQUAL) + { + UnityPrint(UnityStrNotEqual); + } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ + do \ + { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ + } while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8 *)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16 *)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64 *)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32 *)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char *)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char *)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) \ + return 1; \ + if (UNITY_NAN_CHECK) \ + return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) \ + (diff) = -(diff); \ + if ((delta) < 0) \ + (delta) = -(delta); \ + return !(isnan(diff) || isinf(diff) || ((diff) > (delta))) +/* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN +#define UNITY_NAN_CHECK isnan(expected) && isnan(actual) +#else +#define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do \ + { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else +#define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT *expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT *actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT *ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT *ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (isinf(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (isnan(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) + { + failed = 1; + } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) + { + failed = 1; + } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) + { + failed = 0; + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) + { + UnityPrint(UnityStrGt); + } + if (compare & UNITY_SMALLER_THAN) + { + UnityPrint(UnityStrLt); + } + if (compare & UNITY_EQUAL_TO) + { + UnityPrint(UnityStrOrEqual); + } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char *trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !isinf(actual) && !isnan(actual); + break; + + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE *expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE *actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE *ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE *ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (isinf(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (isnan(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) + { + failed = 1; + } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) + { + failed = 1; + } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) + { + failed = 0; + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) + { + UnityPrint(UnityStrGt); + } + if (compare & UNITY_SMALLER_THAN) + { + UnityPrint(UnityStrLt); + } + if (compare & UNITY_EQUAL_TO) + { + UnityPrint(UnityStrOrEqual); + } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char *trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !isinf(actual) && !isnan(actual); + break; + + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8 *)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT8 *)expected; + actual_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT8 *)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16 *)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT16 *)expected; + actual_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT16 *)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64 *)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT64 *)expected; + actual_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT64 *)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32 *)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32 *)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT32 *)expected; + actual_val = (UNITY_INT) * (UNITY_PTR_ATTRIBUTE const UNITY_UINT32 *)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char *)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char *)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char *expected, + const char *actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char *expected, + const char *actual, + const UNITY_UINT32 length, + const char *msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char **actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char *expd = NULL; + const char *act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void *)expected == (const void *)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char *)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char *const *)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char *ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char *)expected; + UNITY_PTR_ATTRIBUTE const unsigned char *ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char *)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char *)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch (size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier +{ + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ + do \ + { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ + } while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char *format, va_list va) +{ + const char *pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, 8); + break; + } + case 'p': + { + const unsigned int number = va_arg(va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 8); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char *string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char *format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char *msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifdef UNITY_PRINT_TEST_CONTEXT + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char *msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char *msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char *FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char *filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char *filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); + UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char *UnityOptionIncludeNamed = NULL; +char *UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char **argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +int IsStringInBiggerString(const char *longstring, const char *shortstring) +{ + const char *lptr = longstring; + const char *sptr = shortstring; + const char *lnext = lptr; + + if (*sptr == '*') + { + return 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + /* We're done if we match the entire string or up to a wildcard */ + if (*sptr == '*') + return 1; + if (*sptr == ',') + return 1; + if (*sptr == '"') + return 1; + if (*sptr == '\'') + return 1; + if (*sptr == ':') + return 2; + if (*sptr == 0) + return 1; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +int UnityStringArgumentMatches(const char *str) +{ + int retval; + const char *ptr1; + const char *ptr2; + const char *ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/User/lib/unity/unity.h b/User/lib/unity/unity.h new file mode 100644 index 0000000..e321a1d --- /dev/null +++ b/User/lib/unity/unity.h @@ -0,0 +1,687 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 5 +#define UNITY_VERSION_BUILD 4 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...) and/or TEST_RANGE(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), __VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out + * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ +#define TEST_FILE(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/User/lib/unity/unity_config.h b/User/lib/unity/unity_config.h new file mode 100644 index 0000000..f246a51 --- /dev/null +++ b/User/lib/unity/unity_config.h @@ -0,0 +1,241 @@ +/* Unity Configuration + * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529 + * Update: December 29th, 2016 + * See Also: Unity/docs/UnityConfigurationGuide.pdf + * + * Unity is designed to run on almost anything that is targeted by a C compiler. + * It would be awesome if this could be done with zero configuration. While + * there are some targets that come close to this dream, it is sadly not + * universal. It is likely that you are going to need at least a couple of the + * configuration options described in this document. + * + * All of Unity's configuration options are `#defines`. Most of these are simple + * definitions. A couple are macros with arguments. They live inside the + * unity_internals.h header file. We don't necessarily recommend opening that + * file unless you really need to. That file is proof that a cross-platform + * library is challenging to build. From a more positive perspective, it is also + * proof that a great deal of complexity can be centralized primarily to one + * place in order to provide a more consistent and simple experience elsewhere. + * + * Using These Options + * It doesn't matter if you're using a target-specific compiler and a simulator + * or a native compiler. In either case, you've got a couple choices for + * configuring these options: + * + * 1. Because these options are specified via C defines, you can pass most of + * these options to your compiler through command line compiler flags. Even + * if you're using an embedded target that forces you to use their + * overbearing IDE for all configuration, there will be a place somewhere in + * your project to configure defines for your compiler. + * 2. You can create a custom `unity_config.h` configuration file (present in + * your toolchain's search paths). In this file, you will list definitions + * and macros specific to your target. All you must do is define + * `UNITY_INCLUDE_CONFIG_H` and Unity will rely on `unity_config.h` for any + * further definitions it may need. + */ + +#ifndef UNITY_CONFIG_H +#define UNITY_CONFIG_H + +/* ************************* AUTOMATIC INTEGER TYPES *************************** + * C's concept of an integer varies from target to target. The C Standard has + * rules about the `int` matching the register size of the target + * microprocessor. It has rules about the `int` and how its size relates to + * other integer types. An `int` on one target might be 16 bits while on another + * target it might be 64. There are more specific types in compilers compliant + * with C99 or later, but that's certainly not every compiler you are likely to + * encounter. Therefore, Unity has a number of features for helping to adjust + * itself to match your required integer sizes. It starts off by trying to do it + * automatically. + **************************************************************************** */ + +/* The first attempt to guess your types is to check `limits.h`. Some compilers + * that don't support `stdint.h` could include `limits.h`. If you don't + * want Unity to check this file, define this to make it skip the inclusion. + * Unity looks at UINT_MAX & ULONG_MAX, which were available since C89. + */ +#define UNITY_EXCLUDE_LIMITS_H + +/* The second thing that Unity does to guess your types is check `stdint.h`. + * This file defines `UINTPTR_MAX`, since C99, that Unity can make use of to + * learn about your system. It's possible you don't want it to do this or it's + * possible that your system doesn't support `stdint.h`. If that's the case, + * you're going to want to define this. That way, Unity will know to skip the + * inclusion of this file and you won't be left with a compiler error. + */ +/* #define UNITY_EXCLUDE_STDINT_H */ + +/* ********************** MANUAL INTEGER TYPE DEFINITION *********************** + * If you've disabled all of the automatic options above, you're going to have + * to do the configuration yourself. There are just a handful of defines that + * you are going to specify if you don't like the defaults. + **************************************************************************** */ + +/* Define this to be the number of bits an `int` takes up on your system. The + * default, if not auto-detected, is 32 bits. + * + * Example: + */ +/* #define UNITY_INT_WIDTH 16 */ + +/* Define this to be the number of bits a `long` takes up on your system. The + * default, if not autodetected, is 32 bits. This is used to figure out what + * kind of 64-bit support your system can handle. Does it need to specify a + * `long` or a `long long` to get a 64-bit value. On 16-bit systems, this option + * is going to be ignored. + * + * Example: + */ +/* #define UNITY_LONG_WIDTH 16 */ + +/* Define this to be the number of bits a pointer takes up on your system. The + * default, if not autodetected, is 32-bits. If you're getting ugly compiler + * warnings about casting from pointers, this is the one to look at. + * + * Example: + */ +#define UNITY_POINTER_WIDTH 64 + +/* Unity will automatically include 64-bit support if it auto-detects it, or if + * your `int`, `long`, or pointer widths are greater than 32-bits. Define this + * to enable 64-bit support if none of the other options already did it for you. + * There can be a significant size and speed impact to enabling 64-bit support + * on small targets, so don't define it if you don't need it. + */ +/* #define UNITY_INCLUDE_64 */ + +/* *************************** FLOATING POINT TYPES **************************** + * In the embedded world, it's not uncommon for targets to have no support for + * floating point operations at all or to have support that is limited to only + * single precision. We are able to guess integer sizes on the fly because + * integers are always available in at least one size. Floating point, on the + * other hand, is sometimes not available at all. Trying to include `float.h` on + * these platforms would result in an error. This leaves manual configuration as + * the only option. + **************************************************************************** */ + +/* By default, Unity guesses that you will want single precision floating point + * support, but not double precision. It's easy to change either of these using + * the include and exclude options here. You may include neither, just float, + * or both, as suits your needs. + */ +#define UNITY_EXCLUDE_FLOAT +#define UNITY_INCLUDE_DOUBLE +/* #define UNITY_EXCLUDE_DOUBLE */ + +/* For features that are enabled, the following floating point options also + * become available. + */ + +/* Unity aims for as small of a footprint as possible and avoids most standard + * library calls (some embedded platforms don't have a standard library!). + * Because of this, its routines for printing integer values are minimalist and + * hand-coded. To keep Unity universal, though, we eventually chose to develop + * our own floating point print routines. Still, the display of floating point + * values during a failure are optional. By default, Unity will print the + * actual results of floating point assertion failures. So a failed assertion + * will produce a message like "Expected 4.0 Was 4.25". If you would like less + * verbose failure messages for floating point assertions, use this option to + * give a failure message `"Values Not Within Delta"` and trim the binary size. + */ +/* #define UNITY_EXCLUDE_FLOAT_PRINT */ + +/* If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C + * floats. If your compiler supports a specialty floating point type, you can + * always override this behavior by using this definition. + * + * Example: + */ +/* #define UNITY_FLOAT_TYPE float16_t */ + +/* If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard + * C doubles. If you would like to change this, you can specify something else + * by using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long + * double` could enable gargantuan floating point types on your 64-bit processor + * instead of the standard `double`. + * + * Example: + */ +/* #define UNITY_DOUBLE_TYPE long double */ + +/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as + * documented in the Unity Assertion Guide, you will learn that they are not + * really asserting that two values are equal but rather that two values are + * "close enough" to equal. "Close enough" is controlled by these precision + * configuration options. If you are working with 32-bit floats and/or 64-bit + * doubles (the normal on most processors), you should have no need to change + * these options. They are both set to give you approximately 1 significant bit + * in either direction. The float precision is 0.00001 while the double is + * 10^-12. For further details on how this works, see the appendix of the Unity + * Assertion Guide. + * + * Example: + */ +/* #define UNITY_FLOAT_PRECISION 0.001f */ +/* #define UNITY_DOUBLE_PRECISION 0.001f */ + +/* *************************** MISCELLANEOUS *********************************** + * Miscellaneous configuration options for Unity + **************************************************************************** */ + +/* Unity uses the stddef.h header included in the C standard library for the + * "NULL" macro. Define this in order to disable the include of stddef.h. If you + * do this, you have to make sure to provide your own "NULL" definition. + */ +/* #define UNITY_EXCLUDE_STDDEF_H */ + +/* Define this to enable the unity formatted print macro: + * "TEST_PRINTF" + */ +/* #define UNITY_INCLUDE_PRINT_FORMATTED */ + +/* *************************** TOOLSET CUSTOMIZATION *************************** + * In addition to the options listed above, there are a number of other options + * which will come in handy to customize Unity's behavior for your specific + * toolchain. It is possible that you may not need to touch any of these but + * certain platforms, particularly those running in simulators, may need to jump + * through extra hoops to operate properly. These macros will help in those + * situations. + **************************************************************************** */ + +/* By default, Unity prints its results to `stdout` as it runs. This works + * perfectly fine in most situations where you are using a native compiler for + * testing. It works on some simulators as well so long as they have `stdout` + * routed back to the command line. There are times, however, where the + * simulator will lack support for dumping results or you will want to route + * results elsewhere for other reasons. In these cases, you should define the + * `UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time + * (as an `int`, since this is the parameter type of the standard C `putchar` + * function most commonly used). You may replace this with whatever function + * call you like. + * + * Example: + * Say you are forced to run your test suite on an embedded processor with no + * `stdout` option. You decide to route your test result output to a custom + * serial `RS232_putc()` function you wrote like thus: + */ +/* #define UNITY_OUTPUT_CHAR(a) RS232_putc(a) */ +/* #define UNITY_OUTPUT_CHAR_HEADER_DECLARATION RS232_putc(int) */ +/* #define UNITY_OUTPUT_FLUSH() RS232_flush() */ +/* #define UNITY_OUTPUT_FLUSH_HEADER_DECLARATION RS232_flush(void) */ +/* #define UNITY_OUTPUT_START() RS232_config(115200,1,8,0) */ +/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */ + +/* Some compilers require a custom attribute to be assigned to pointers, like + * `near` or `far`. In these cases, you can give Unity a safe default for these + * by defining this option with the attribute you would like. + * + * Example: + */ +/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */ +/* #define UNITY_PTR_ATTRIBUTE near */ + +/* Print execution time of each test when executed in verbose mode + * + * Example: + * + * TEST - PASS (10 ms) + */ +/* #define UNITY_INCLUDE_EXEC_TIME */ + +#endif /* UNITY_CONFIG_H */ diff --git a/User/lib/unity/unity_internals.h b/User/lib/unity/unity_internals.h new file mode 100644 index 0000000..6075b9a --- /dev/null +++ b/User/lib/unity/unity_internals.h @@ -0,0 +1,1181 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if !defined(STM32) || defined(__clang__) +#define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else +#define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +#ifndef UNITY_NORETURN +#if defined(__cplusplus) +#if __cplusplus >= 201103L +#define UNITY_NORETURN [[noreturn]] +#endif +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if defined(_WIN32) && defined(_MSC_VER) +/* We are using MSVC compiler on Windows platform. */ +/* Not all Windows SDKs supports , but compiler can support C11: */ +/* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ +/* Not sure, that Mingw compilers has Windows SDK headers at all. */ +#include +#endif + +/* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ +/* Mingw GCC should work without that fixes. */ +/* Based on: */ +/* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ +/* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ +#if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) +/* Based on tests and: */ +/* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ +/* https://en.cppreference.com/w/c/language/_Noreturn */ +#define UNITY_NORETURN _Noreturn +#else /* Using newer Windows SDK or not MSVC compiler */ +#include +#define UNITY_NORETURN noreturn +#endif +#endif +#endif +#ifndef UNITY_NORETURN +#define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH +#ifdef UINT_MAX +#if (UINT_MAX == 0xFFFF) +#define UNITY_INT_WIDTH (16) +#elif (UINT_MAX == 0xFFFFFFFF) +#define UNITY_INT_WIDTH (32) +#elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) +#define UNITY_INT_WIDTH (64) +#endif +#else /* Set to default */ +#define UNITY_INT_WIDTH (32) +#endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH +#ifdef ULONG_MAX +#if (ULONG_MAX == 0xFFFF) +#define UNITY_LONG_WIDTH (16) +#elif (ULONG_MAX == 0xFFFFFFFF) +#define UNITY_LONG_WIDTH (32) +#elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) +#define UNITY_LONG_WIDTH (64) +#endif +#else /* Set to default */ +#define UNITY_LONG_WIDTH (32) +#endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH +#ifdef UINTPTR_MAX +#if (UINTPTR_MAX <= 0xFFFF) +#define UNITY_POINTER_WIDTH (16) +#elif (UINTPTR_MAX <= 0xFFFFFFFF) +#define UNITY_POINTER_WIDTH (32) +#elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) +#define UNITY_POINTER_WIDTH (64) +#endif +#else /* Set to default */ +#define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH +#endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) +typedef unsigned char UNITY_UINT8; +typedef unsigned short UNITY_UINT16; +typedef unsigned int UNITY_UINT32; +typedef signed char UNITY_INT8; +typedef signed short UNITY_INT16; +typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) +typedef unsigned char UNITY_UINT8; +typedef unsigned int UNITY_UINT16; +typedef unsigned long UNITY_UINT32; +typedef signed char UNITY_INT8; +typedef signed int UNITY_INT16; +typedef signed long UNITY_INT32; +#else +#error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 +#if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 +#define UNITY_SUPPORT_64 +#endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 +/* No 64-bit Support */ +typedef UNITY_UINT32 UNITY_UINT; +typedef UNITY_INT32 UNITY_INT; +#define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else +/* 64-bit Support */ +#if (UNITY_LONG_WIDTH == 32) +typedef unsigned long long UNITY_UINT64; +typedef signed long long UNITY_INT64; +#elif (UNITY_LONG_WIDTH == 64) +typedef unsigned long UNITY_UINT64; +typedef signed long UNITY_INT64; +#else +#error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) +#endif +typedef UNITY_UINT64 UNITY_UINT; +typedef UNITY_INT64 UNITY_INT; +#define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) +#define UNITY_PTR_TO_INT UNITY_INT32 +#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) +#define UNITY_PTR_TO_INT UNITY_INT64 +#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) +#define UNITY_PTR_TO_INT UNITY_INT16 +#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else +#error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE +#define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR +#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void * +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isinf & isnan macros should be provided by math.h */ +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define isinf(n) (isnan((n) - (n)) && !isnan(n)) +#endif + +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define isnan(n) ((n != n) ? 1 : 0) +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE +#else +#undef UNITY_INCLUDE_DOUBLE +#endif + +#ifndef UNITY_EXCLUDE_FLOAT +#ifndef UNITY_DOUBLE_TYPE +#define UNITY_DOUBLE_TYPE double +#endif +typedef UNITY_FLOAT UNITY_DOUBLE; +/* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ +#endif + +#else + +/* Double Floating Point Support */ +#ifndef UNITY_DOUBLE_PRECISION +#define UNITY_DOUBLE_PRECISION (1e-12) +#endif + +#ifndef UNITY_DOUBLE_TYPE +#define UNITY_DOUBLE_TYPE double +#endif +typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR +/* Default to using putchar, which is defined in stdio.h */ +#include +#define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else +/* If defined as something else, make sure we declare it here so it's ready for use */ +#ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION +extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; +#endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#ifdef UNITY_USE_FLUSH_STDOUT +/* We want to use the stdout flush utility */ +#include +#define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) +#else +/* We've specified nothing, therefore flush should just be ignored */ +#define UNITY_OUTPUT_FLUSH() (void)0 +#endif +#else +/* If defined as something else, make sure we declare it here so it's ready for use */ +#ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION +extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; +#endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME +#if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) +/* If none any of these macros are defined then try to provide a default implementation */ + +#if defined(UNITY_CLOCK_MS) +/* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ +#define UNITY_TIME_TYPE UNITY_UINT +#define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() +#define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() +#define UNITY_PRINT_EXEC_TIME() \ + { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } +#elif defined(_WIN32) +#include +#define UNITY_TIME_TYPE clock_t +#define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) +#define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) +#define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) +#define UNITY_PRINT_EXEC_TIME() \ + { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } +#elif defined(__unix__) || defined(__APPLE__) +#include +#define UNITY_TIME_TYPE struct timespec +#define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) +#define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) +#define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) +#define UNITY_PRINT_EXEC_TIME() \ + { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } +#endif +#endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() \ + do \ + { /* nothing*/ \ + } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() \ + do \ + { /* nothing*/ \ + } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() \ + do \ + { /* nothing*/ \ + } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char *TestFile; + const char *CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char *CurrentDetail1; + const char *CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char *filename); +int UnityEnd(void); +void UnitySetTestFile(const char *filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char *FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1, d2) +#else +#define UNITY_CLR_DETAILS() \ + do \ + { \ + Unity.CurrentDetail1 = 0; \ + Unity.CurrentDetail2 = 0; \ + } while (0) +#define UNITY_SET_DETAIL(d1) \ + do \ + { \ + Unity.CurrentDetail1 = (d1); \ + Unity.CurrentDetail2 = 0; \ + } while (0) +#define UNITY_SET_DETAILS(d1, d2) \ + do \ + { \ + Unity.CurrentDetail1 = (d1); \ + Unity.CurrentDetail2 = (d2); \ + } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char *string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char *format, ...); +#endif + +void UnityPrintLen(const char *string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char *expected, + const char *actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char *expected, + const char *actual, + const UNITY_UINT32 length, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char **actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char *message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char *message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char *message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char *message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char *message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT *expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT *actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE *expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE *actual, + const UNITY_UINT32 num_elements, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_PROTECT() 1 +#define TEST_ABORT() return +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS +#ifdef __STDC_VERSION__ +#if __STDC_VERSION__ >= 199901L +#define UNITY_SUPPORT_VARIADIC_MACROS +#endif +#endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) +#define TEST_CASE(...) +#endif +#if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) +#define TEST_RANGE(...) +#endif +#endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char **argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail((message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore((message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) \ + do \ + { \ + if (condition) \ + { /* nothing*/ \ + } \ + else \ + { \ + UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message)); \ + } \ + } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (UNITY_LINE_TYPE)(line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8)(expected), (UNITY_INT)(UNITY_INT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8)(expected), (UNITY_INT)(UNITY_UINT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8)(expected), (UNITY_INT)(UNITY_INT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8)(expected), (UNITY_INT)(UNITY_INT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8)(threshold), (UNITY_INT)(UNITY_UINT8)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8)(threshold), (UNITY_INT)(UNITY_INT8)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8)(delta), (UNITY_INT)(UNITY_INT8)(expected), (UNITY_INT)(UNITY_INT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8)(delta), (UNITY_INT)(UNITY_INT8)(expected), (UNITY_INT)(UNITY_INT8)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char *)(expected), (const char *)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char *)(expected), (const char *)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char **)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8)(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8)(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8)(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT)(expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char **)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8)(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT *)(expected), (const UNITY_FLOAT *)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT *)(expected), (const UNITY_FLOAT *)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT *)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE *)(expected), (const UNITY_DOUBLE *)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE *)(expected), (const UNITY_DOUBLE *)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE *)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/User/system/bsp/adcs.c b/User/system/bsp/adcs.c new file mode 100644 index 0000000..5fb5b3b --- /dev/null +++ b/User/system/bsp/adcs.c @@ -0,0 +1,403 @@ +/** + * @file adcs.c + * @author xxx + * @date 2023-09-04 15:59:16 + * @brief LL库ADC驱动 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "adcs.h" +#include "sys.h" + +adcs_t adcs[ADCS_MAX]; + +static uint8_t adc_get_channels_count(uint32_t channnels); // 通过用户配置的通道号获取通道数量 + +/** + * @brief ADC初始化 + * @param {adcs_e} num ADC编号 + * @param {ADC_TypeDef} *adc ADC外设 + * @param {DMA_TypeDef} *dma DMA外设 + * @param {uint32_t} dma_channel DMA通道 + * @param {uint8_t} adc_cct ADC采样次数 + * @param {uint32_t} channels 存储数据所在的序列号 + * @return {*} + * @note TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数) + */ +void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_channel, uint8_t adc_cct, uint32_t channels) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + DBG_ASSERT(adc != NULL __DBG_LINE); + DBG_ASSERT(dma != NULL __DBG_LINE); + DBG_ASSERT(adc_cct > 0 __DBG_LINE); + + adcs_t *p = &adcs[num]; + osel_memset((uint8_t *)p, 0, sizeof(adcs_t)); + p->adc = adc; + p->dma = dma; + p->dma_channel = dma_channel; + p->channels.data = channels; + p->adc_cct = adc_cct; + p->adc_chans_count = adc_get_channels_count(channels); + p->adc_sum = adc_cct * p->adc_chans_count; + +#if defined(SRAM2_BASE) // SRAM2速度更快 + p->adc_value = (uint16_t *)osel_mem_alloc2(sizeof(uint16_t) * p->adc_sum); +#else + p->adc_value = (uint16_t *)osel_mem_alloc(sizeof(uint16_t) * p->adc_sum); +#endif + + DBG_ASSERT(p->adc_value != NULL __DBG_LINE); + osel_memset((uint8_t *)p->adc_value, 0, sizeof(uint16_t) * p->adc_sum); + + uint32_t backup_setting_adc_dma_transfer = 0U; + backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(p->adc); + LL_ADC_REG_SetDMATransfer(p->adc, LL_ADC_REG_DMA_TRANSFER_NONE); + + // ADC开始校准 + LL_ADC_StartCalibration(p->adc, LL_ADC_SINGLE_ENDED); + // 等待校准完成 + while (LL_ADC_IsCalibrationOnGoing(p->adc)) + ; + LL_ADC_REG_SetDMATransfer(p->adc, backup_setting_adc_dma_transfer); + LL_mDelay(10); + LL_ADC_EnableIT_OVR(p->adc); + LL_ADC_Enable(p->adc); + LL_mDelay(10); + + LL_DMA_SetDataLength(p->dma, p->dma_channel, p->adc_sum); + LL_DMA_SetPeriphAddress(p->dma, p->dma_channel, LL_ADC_DMA_GetRegAddr(p->adc, LL_ADC_DMA_REG_REGULAR_DATA)); + LL_DMA_SetMemoryAddress(p->dma, p->dma_channel, (uint32_t)p->adc_value); + LL_DMA_EnableChannel(p->dma, p->dma_channel); + + if (backup_setting_adc_dma_transfer == LL_ADC_REG_DMA_TRANSFER_UNLIMITED) + { + LL_ADC_REG_StartConversion(p->adc); // 开始转换 + } +} + +/** + * @brief ADC反初始化 + * @param {adcs_e} num ADC编号 + * @return {*} + * @note + */ +void adc_dinit(adcs_e num) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + adcs_t *p = &adcs[num]; + LL_ADC_REG_StopConversion(p->adc); + LL_DMA_DisableChannel(p->dma, p->dma_channel); + LL_ADC_Disable(p->adc); + if (p->adc_value != NULL) + { +#if defined(SRAM2_BASE) + osel_mem_free2((uint16_t *)p->adc_value); +#else + osel_mem_free((uint16_t *)p->adc_value); +#endif + } +} +/** + * @brief 获取ADC转换结果,只需要第一个值 + * @param {adcs_e} num + * @param {uint8_t} chan + * @return {*} + * @note + */ +uint16_t adc_result_only_one(adcs_e num, uint8_t chan) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + adcs_t *p = &adcs[num]; + DBG_ASSERT(p != NULL __DBG_LINE); + uint16_t(*gram)[p->adc_chans_count] = (uint16_t(*)[p->adc_chans_count])p->adc_value; + return gram[0][chan]; +} + +/** + * @brief 中位值平均滤波,获取ADC转换结果 + * @param {adcs_e} num ADC编号 + * @param {uint8_t} chan 存储数据所在的序列号 + * @return {*} + * @note + */ +uint16_t adc_result_median_average(adcs_e num, uint8_t chan) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + uint16_t res = 0; + adcs_t *p = &adcs[num]; + DBG_ASSERT(p != NULL __DBG_LINE); + uint16_t adc_temp[p->adc_cct]; + uint32_t adc_sum = 0; + + for (uint8_t i = 0; i < p->adc_cct; i++) + { + adc_temp[i] = p->adc_value[i * p->adc_chans_count + chan]; + } + + quicksort(adc_temp, 0, p->adc_cct - 1); + + for (uint8_t i = 0; i < p->adc_cct; i++) // 遍历所有ADC通道 + { + adc_sum += adc_temp[i]; // 将每个ADC通道的数据累加到adc_sum中 + } + + res = adc_sum / p->adc_cct; + return res; +} + +/** + * @brief 中位值滤波,获取ADC转换结果 + * @param {adcs_e} num ADC编号 + * @param {uint8_t} chan 存储数据所在的序列号 + * @return {*} + * @note + */ +uint16_t adc_result_median(adcs_e num, uint8_t chan) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + uint16_t res = 0; + adcs_t *p = &adcs[num]; + uint16_t adc_temp[p->adc_cct]; + for (uint8_t i = 0; i < p->adc_cct; i++) + { + adc_temp[i] = p->adc_value[i * p->adc_chans_count + chan]; + } + // 使用快速排序 + quicksort(adc_temp, 0, p->adc_cct - 1); + res = adc_temp[p->adc_cct / 2]; + return res; +} + +/** + * @brief 平均值,获取ADC转换结果 + * @param {adcs_e} num ADC编号 + * @param {uint8_t} chan 存储数据所在的序列号 + * @return {*} + * @note + */ +uint16_t adc_result_average(adcs_e num, uint8_t chan) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + adcs_t *p = &adcs[num]; + DBG_ASSERT(p != NULL __DBG_LINE); + DBG_ASSERT(p->adc_cct != 0 __DBG_LINE); // 避免除以零的错误 + uint32_t adc_sum = 0; + uint16_t(*gram)[p->adc_chans_count] = (uint16_t(*)[p->adc_chans_count])p->adc_value; + + for (uint8_t i = 0; i < p->adc_cct; i++) + { + uint32_t next_sum = adc_sum + gram[i][chan]; + DBG_ASSERT(next_sum >= adc_sum __DBG_LINE); // 避免溢出 + adc_sum = next_sum; + } + + return adc_sum / p->adc_cct; +} + +/** + * @brief N次平均值,获取ADC转换结果 + * @param {adcs_e} num ADC编号 + * @param {uint8_t} chan 存储数据所在的序列号 + * @return {*} + * @note + */ +uint16_t adc_result_n_average(adcs_e num, uint8_t chan) +{ + DBG_ASSERT(num < ADCS_MAX __DBG_LINE); + uint16_t res = 0; + uint32_t adc_sum = 0; + adcs_t *p = &adcs[num]; + DBG_ASSERT(p != NULL __DBG_LINE); + uint16_t adc_temp[p->adc_cct]; + uint8_t n = p->adc_cct / 4; + uint8_t count = p->adc_cct > (2 * n) ? n : 0; + + for (uint8_t i = 0; i < p->adc_cct; i++) + { + adc_temp[i] = p->adc_value[i * p->adc_chans_count + chan]; + } + + quicksort(adc_temp, 0, p->adc_cct - 1); + + for (uint8_t i = count; i < p->adc_cct - count; i++) + { + adc_sum += adc_temp[i]; + } + res = adc_sum / (p->adc_cct - 2 * count); + return res; +} + +/** + * @brief 计算内部温度 + * @param {uint16_t} adc_value ADC转换结果 + * @return {*} + * @note 计算公式为:(measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR) * (int32_t)(130 - 30) / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR)) + 30 + */ +float32 adc_result_temperature(uint16_t adc_value) +{ +#define TEMP130_CAL_ADDR ((uint16_t *)((uint32_t)0x1FFF75A8)) +#define TEMP30_CAL_ADDR ((uint16_t *)((uint32_t)0x1FFF75CA)) +#define VDD_CALIB ((uint16_t)(300)) +#define VDD_APPLI ((uint16_t)(330)) + float32 res; + res = ((adc_value * VDD_APPLI / VDD_CALIB) - + (int32_t)*TEMP30_CAL_ADDR); + res = res * (int32_t)(130 - 30); + res = res / (int32_t)(*TEMP130_CAL_ADDR - + *TEMP30_CAL_ADDR); + res = res + 30; + return res * 0.1f; +} + +/** + * @brief 计算内部电压 + * @param {uint16_t} adc_value ADC转换结果 + * @return {*} + * @note + */ +uint16_t adc_result_value_local(uint16_t adc_value) +{ + return (1224.0 / adc_value) * 4095; +} + +/** + * @brief ADC DMA转换回调函数 +{ + * @param {adcs_e} num ADC编号 + * @return {*} + * @note + */ +void adc_dma_callback(adcs_e num) +{ + adcs_t *p = &adcs[num]; + DBG_ASSERT(p != NULL __DBG_LINE); + if (LL_DMA_IsActiveFlag_TC1(p->dma) != 0) + { + LL_DMA_ClearFlag_TC1(p->dma); + // 停止ADC转换 + LL_ADC_REG_StopConversion(p->adc); + // 关闭ADC,可以不关闭但是校准无法清除 + // LL_ADC_Disable(p->adc); + } + // 检查DMA1的传输错误标志是否为1,如果是,则清除该标志 + if (LL_DMA_IsActiveFlag_TE1(p->dma) != 0) + { + LL_DMA_ClearFlag_TE1(p->dma); + } +} + +/** + * @brief ADC回调函数 + * @param {adcs_e} num ADC编号 + * @return {*} + * @note + */ +void adc_env_callback(adcs_e num) +{ + adcs_t *p = &adcs[num]; + DBG_ASSERT(p != NULL __DBG_LINE); + if (LL_ADC_IsActiveFlag_OVR(p->adc) != 0) + { + p->ovr_count++; + LL_ADC_REG_StopConversion(p->adc); + LL_DMA_DisableChannel(p->dma, p->dma_channel); + + LL_DMA_SetDataLength(p->dma, p->dma_channel, p->adc_sum); + LL_DMA_SetPeriphAddress(p->dma, p->dma_channel, LL_ADC_DMA_GetRegAddr(p->adc, LL_ADC_DMA_REG_REGULAR_DATA)); + LL_DMA_SetMemoryAddress(p->dma, p->dma_channel, (uint32_t)p->adc_value); + LL_DMA_EnableChannel(p->dma, p->dma_channel); + + LL_ADC_ClearFlag_OVR(p->adc); + LL_ADC_ClearFlag_EOC(p->adc); + LL_ADC_REG_StartConversion(p->adc); // 开始转换 + } +} + +/** + * @brief 通过用户配置的通道号获取通道数量 + * @param {uint32_t} channnels 存储数据所在的序列号 + * @return {*} + * @note + */ +static uint8_t adc_get_channels_count(uint32_t channnels) +{ + uint8_t ch_num = 0; + if (BIT_IS_SET(channnels, IN0)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN1)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN2)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN3)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN4)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN5)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN6)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN7)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN8)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN9)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN10)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN11)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN12)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN13)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN14)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, IN15)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, INVREF)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, INVBAT)) + { + ch_num++; + } + if (BIT_IS_SET(channnels, INTEMP)) + { + ch_num++; + } + return ch_num; +} diff --git a/User/system/bsp/adcs.h b/User/system/bsp/adcs.h new file mode 100644 index 0000000..5d9fedf --- /dev/null +++ b/User/system/bsp/adcs.h @@ -0,0 +1,217 @@ +/** + * @file adcs.h + * @brief Header file for ADC driver using LL library. + * + * This file contains the declarations and documentation for the ADC driver + * using the LL (Low-Level) library. + * + * @date 2023-09-04 15:59:16 + * @author xxx + * @version 1.0 + * + * @note This code is proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + * + * @note All rights reserved by xxx. + */ + +#ifndef __ADCS_H__ +#define __ADCS_H__ + +#include "lib.h" +#include "main.h" +#define ADC_CHANNEL_MAX 18 // Maximum number of ADC channels +typedef enum +{ + IN0 = BIT0, + IN1 = BIT1, + IN2 = BIT2, + IN3 = BIT3, + IN4 = BIT4, + IN5 = BIT5, + IN6 = BIT6, + IN7 = BIT7, + IN8 = BIT8, + IN9 = BIT9, + IN10 = BIT10, + IN11 = BIT11, + IN12 = BIT12, + IN13 = BIT13, + IN14 = BIT14, + IN15 = BIT15, + INTEMP = BIT16, + INVBAT = BIT17, + INVREF = BIT18, +} adc_num_e; // ADC channel number + +typedef enum +{ + ADCS_1, + ADCS_2, + ADCS_3, + ADCS_MAX, +} adcs_e; // ADC number + +typedef union +{ + uint32_t data; + struct + { + uint32_t in0 : 1; + uint32_t in1 : 1; + uint32_t in2 : 1; + uint32_t in3 : 1; + uint32_t in4 : 1; + uint32_t in5 : 1; + uint32_t in6 : 1; + uint32_t in7 : 1; + uint32_t in8 : 1; + uint32_t in9 : 1; + uint32_t in10 : 1; + uint32_t in11 : 1; + uint32_t in12 : 1; + uint32_t in13 : 1; + uint32_t in14 : 1; + uint32_t in15 : 1; + uint32_t invref : 1; + uint32_t intemp : 1; + }; +} adcs_channels_u; // ADC channels + +typedef struct +{ + ADC_TypeDef *adc; // ADC peripheral + DMA_TypeDef *dma; // DMA peripheral + uint32_t dma_channel; // DMA channel + adcs_channels_u channels; // ADC channels + uint32_t ovr_count; // ADC overflow count + + uint8_t adc_cct; // Channel single acquisition count + uint8_t adc_chans_count; // Number of channels + uint16_t adc_sum; // Channel acquisition count + __IO uint16_t *adc_value; // Address to store ADC conversion results +} adcs_t; + +/** + * @brief Initializes the ADC module. + * + * This function initializes the ADC module with the specified parameters. + * + * @param num The ADC number. + * @param adc Pointer to the ADC peripheral. + * @param dma Pointer to the DMA peripheral. + * @param dma_channel The DMA channel number. + * @param adc_cct The ADC continuous conversion mode. + * @param channels The number of ADC channels to be converted. + */ +extern void adc_init(adcs_e num, ADC_TypeDef *adc, DMA_TypeDef *dma, uint32_t dma_channel, uint8_t adc_cct, uint32_t channels); + +/** + * @brief Deinitializes the ADC module. + * + * This function deinitializes the ADC module. + * + * @param num The ADC number. + */ +extern void adc_dinit(adcs_e num); + +/** + * @brief Gets the ADC conversion result for a single channel. + * + * This function gets the ADC conversion result for a single channel. + * It returns only the first converted value. + * + * @param num The ADC number. + * @param chan The ADC channel number. + * @return The ADC conversion result. + */ +extern uint16_t adc_result_only_one(adcs_e num, uint8_t chan); + +/** + * @brief Gets the ADC conversion result using median average filtering. + * + * This function gets the ADC conversion result for a single channel. + * It applies median average filtering to the converted values. + * + * @param num The ADC number. + * @param chan The ADC channel number. + * @return The ADC conversion result. + */ +extern uint16_t adc_result_median_average(adcs_e num, uint8_t chan); + +/** + * @brief Gets the ADC conversion result using median filtering. + * + * This function gets the ADC conversion result for a single channel. + * It applies median filtering to the converted values. + * + * @param num The ADC number. + * @param chan The ADC channel number. + * @return The ADC conversion result. + */ +extern uint16_t adc_result_median(adcs_e num, uint8_t chan); + +/** + * @brief Gets the ADC conversion result using average filtering. + * + * This function gets the ADC conversion result for a single channel. + * It applies average filtering to the converted values. + * + * @param num The ADC number. + * @param chan The ADC channel number. + * @return The ADC conversion result. + */ +extern uint16_t adc_result_average(adcs_e num, uint8_t chan); + +/** + * @brief Gets the ADC conversion result using N-times average filtering. + * + * This function gets the ADC conversion result for a single channel. + * It applies N-times average filtering to the converted values. + * + * @param num The ADC number. + * @param chan The ADC channel number. + * @return The ADC conversion result. + */ +extern uint16_t adc_result_n_average(adcs_e num, uint8_t chan); + +/** + * @brief Calculates the temperature from the ADC conversion result. + * + * This function calculates the temperature in degrees Celsius + * from the ADC conversion result of the internal temperature sensor. + * + * @param adc_value The ADC conversion result. + * @return The temperature in degrees Celsius. + */ +extern float32 adc_result_temperature(uint16_t adc_value); + +/** + * @brief Calculates the voltage from the ADC conversion result. + * + * This function calculates the voltage in millivolts + * from the ADC conversion result of the internal voltage reference. + * + * @param adc_value The ADC conversion result. + * @return The voltage in millivolts. + */ +extern uint16_t adc_result_value_local(uint16_t adc_value); + +/** + * @brief ADC environment callback function. + * + * This function is called when an ADC conversion is completed. + * + * @param num The ADC number. + */ +extern void adc_env_callback(adcs_e num); + +/** + * @brief DMA callback function for ADC. + * + * This function is called when a DMA transfer for ADC is completed. + * + * @param num The ADC number. + */ +extern void adc_dma_callback(adcs_e num); +#endif // __ADCS_H__ diff --git a/User/system/bsp/bsp.h b/User/system/bsp/bsp.h new file mode 100644 index 0000000..886c3c0 --- /dev/null +++ b/User/system/bsp/bsp.h @@ -0,0 +1,51 @@ +/** + * @file bsp.h + * @brief This file contains the declarations and definitions for the BSP (Board Support Package) module. + * + * The BSP module provides functions and configurations specific to the hardware platform, such as initializing + * peripherals, configuring GPIO pins, and managing interrupts. + * + * @author xxx + * @date 2023-12-27 14:44:03 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __BSP_H__ +#define __BSP_H__ + +#include "gpios.h" +#include "adcs.h" +#include "dacs.h" +#include "tims.h" +#include "pwms.h" +#include "uarts.h" +#include "eeprom.h" +#include "spis.h" +#include "i2cs.h" + +/** + * @brief Clears the flags of a DMA channel + * @param DMAX DMAx register base + * @param CHx DMA channel number + * @param Flag a boolean variable that indicates if the transfer is complete + * @note This function should be called within the interrupt service routine of the DMA channel + */ +#define DMA_ClEAR_FLAG(DMAX, CHx, Flag) \ + do \ + { \ + if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \ + { \ + LL_DMA_ClearFlag_TC##CHx(DMAX); \ + LL_DMA_ClearFlag_GI##CHx(DMAX); \ + Flag = TRUE; \ + } \ + if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \ + { \ + LL_DMA_ClearFlag_TE##CHx(DMAX); \ + } \ + if (LL_DMA_IsActiveFlag_GI##CHx(DMAX)) \ + { \ + LL_DMA_ClearFlag_GI##CHx(DMAX); \ + } \ + } while (__LINE__ == -1) + +#endif // __BSP_H__ diff --git a/User/system/bsp/dacs.c b/User/system/bsp/dacs.c new file mode 100644 index 0000000..04c96dc --- /dev/null +++ b/User/system/bsp/dacs.c @@ -0,0 +1,49 @@ +/** + * @file dacs.c + * @brief This file contains the implementation of the DAC module. + * It provides functions to initialize and de-initialize a DAC instance, + * as well as write a 16-bit value to the specified DAC channel. + * @author xxx + * @date 2023-12-27 14:44:03 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#include "dacs.h" + +/** + * @brief Writes a 16-bit value to the specified DAC channel + * + * @param dac pointer to the DAC instance + * @param value 16-bit value to write to the DAC + */ +static void _out(dac_t *dac, uint16_t value) +{ + DAC_OUT(dac->dac, dac->dac_channel, value); +} + +/** + * @brief Initializes a DAC instance + * + * @param dac pointer to the DAC instance + * @param dac_channel DAC channel to use + * @return pointer to the initialized DAC instance + */ +dac_t *dac_create(DAC_TypeDef *dac, uint16_t dac_channel) +{ + dac_t *handle = (dac_t *)osel_mem_alloc(sizeof(dac_t)); + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->dac = dac; + handle->dac_channel = dac_channel; + + handle->out = _out; + return handle; +} + +/** + * @brief De-initializes a DAC instance + * + * @param dac pointer to the DAC instance + */ +void dac_free(dac_t *dac) +{ + osel_mem_free(dac); +} diff --git a/User/system/bsp/dacs.h b/User/system/bsp/dacs.h new file mode 100644 index 0000000..56e68a7 --- /dev/null +++ b/User/system/bsp/dacs.h @@ -0,0 +1,55 @@ +/** + * @file dacs.h + * @brief Header file for DACs module. + * + * This file contains the declarations and definitions for the DACs module. + * DACs (Digital-to-Analog Converters) are used to convert digital signals into analog voltages. + * + * @author xxx + * @date 2023-12-27 14:44:03 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __DACS_H__ +#define __DACS_H__ +#include "dac.h" +#include "lib.h" +#include "main.h" + +/** + * @brief Set the output value for a specific DAC channel. + * @param dac: pointer to the @ref dac_t structure that contains the configuration information for the specified DAC. + * @param value: the output value to be set. + * @retval None + */ +#define DAC_OUT(DACx, DAC_Channel, Data) \ + do \ + { \ + LL_DAC_ConvertData12RightAligned(DACx, DAC_Channel, Data); \ + LL_DAC_TrigSWConversion(DACx, DAC_Channel); \ + } while (__LINE__ == -1) + +/** + * @brief Enable the specified DAC channel. + * @param dac: pointer to the @ref dac_t structure that contains the configuration information for the specified DAC. + * @retval None + */ +#define DAC_START(DACx, DAC_Channel) LL_DAC_Enable(DACx, DAC_Channel) + +/** + * @brief Disable the specified DAC channel. + * @param dac: pointer to the @ref dac_t structure that contains the configuration information for the specified DAC. + * @retval None + */ +#define DAC_STOP(DACx, DAC_Channel) LL_DAC_Disable(DACx, DAC_Channel) + +/** + * @brief Structure definition for the DAC driver. + */ +typedef struct DACS +{ + DAC_TypeDef *dac; + uint16_t dac_channel; + + void (*out)(struct DACS *dac, uint16_t value); +} dac_t; +#endif diff --git a/User/system/bsp/eeprom.c b/User/system/bsp/eeprom.c new file mode 100644 index 0000000..6be9a42 --- /dev/null +++ b/User/system/bsp/eeprom.c @@ -0,0 +1,91 @@ +/** + * @file eeprom.c + * @author xxx + * @date 2023-11-16 10:28:47 + * @brief STM32L072xx EEPROM 驱动 + * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#include "eeprom.h" +#include "main.h" + +#ifdef STM32L072xx +#define PEKEY1 0x89ABCDEF // FLASH_PEKEYR +#define PEKEY2 0x02030405 // FLASH_PEKEYR + +#define LOCK __enable_irq(); // 系统开全局中断 +#define UNLOCK __disable_irq(); // 系统关全局中断 + +/** + * @brief 用于配置读取和写入EEPROM的函数 + * @param {uint32_t} read_addr - 读取地址 + * @param {uint8_t} *data - 存储数据的指针 + * @param {uint16_t} length - 读取或写入的数据长度 + * @return {*} + * @note: 这些函数用于在特定的地址读取或写入数据到EEPROM中。地址和数据以字节为单位,长度以字节为单位。 + */ +void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length) +{ + uint8_t *wAddr; + wAddr = (uint8_t *)(read_addr); + while (length--) + { + *data++ = *wAddr++; + } +} + +/** + * @brief 用于配置写入EEPROM的函数 + * @param {uint32_t} write_addr - 写入地址 + * @param {uint8_t} *data - 存储数据的指针 + * @param {uint16_t} length - 写入的数据长度 + * @return {*} + * @note: 这些函数用于在特定的地址写入数据到EEPROM中。地址和数据以字节为单位,长度以字节为单位。在写入数据之前,需要先解锁EEPROM,写入数据,然后锁定EEPROM。 + */ +void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length) +{ + uint8_t *addr; + addr = (uint8_t *)(write_addr); + UNLOCK + FLASH->PDKEYR = PEKEY1; + FLASH->PDKEYR = PEKEY2; + while (FLASH->PECR & FLASH_PECR_PELOCK) + ; + + while (length--) + { + *addr++ = *data++; + while (FLASH->SR & FLASH_SR_BSY) + ; + } + FLASH->PECR |= FLASH_PECR_PELOCK; + LOCK +} + +#endif // STM32L072xx + +#ifdef STM32L476xx + +/** + * @brief 用于配置读取和写入SRAM2的函数 + * @param {uint32_t} read_addr - 读取地址 + * @param {uint8_t} *data - 存储数据的指针 + * @param {uint16_t} length - 读取或写入的数据长度 + * @return {*} + * @note: 这些函数用于在特定的地址读取或写入数据到SRAM2中。地址和数据以字节为单位,长度以字节为单位。 + */ +void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length) +{ +} + +/** + * @brief 用于配置写入SRAM2的函数 + * @param {uint32_t} write_addr - 写入地址 从0开始 + * @param {uint8_t} *data - 存储数据的指针 + * @param {uint16_t} length - 写入的数据长度 + * @return {*} + * @note: 这些函数用于在特定的地址写入数据到SRAM2中。地址和数据以字节为单位,长度以字节为单位。 + */ +void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length) +{ +} +#endif // STM32L476xx diff --git a/User/system/bsp/eeprom.h b/User/system/bsp/eeprom.h new file mode 100644 index 0000000..41bb951 --- /dev/null +++ b/User/system/bsp/eeprom.h @@ -0,0 +1,7 @@ +#ifndef __EEPROM_H__ +#define __EEPROM_H__ +#include "lib.h" + +extern void chip_eeprom_config_read(uint32_t read_addr, uint8_t *data, uint16_t length); // 读取数据 +extern void chip_eeprom_config_write(uint32_t write_addr, uint8_t *data, uint16_t length); // 写入数据 +#endif // __EEPROM_H__ diff --git a/User/system/bsp/flash.c b/User/system/bsp/flash.c new file mode 100644 index 0000000..8855cb7 --- /dev/null +++ b/User/system/bsp/flash.c @@ -0,0 +1,530 @@ +/** + * @file flash.c + * @author xxx + * @date 2024-02-07 11:49:34 + * @brief + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + * @attention + * + * ST 的官方驱动 LL 库并没有 flash 驱动。这里自己实现。 + * + * 1. 由于在 stm32l4xx_ll_system.h 中存在部分 FLASH 操作函数(ACR寄存器的处理)且不全面 + * 因此这里需要额外处理(重命名) + * + * 2. Main memory + * (1) FLASH_ACR 完成 + * (2) FLASH_PDKEYR 完成 + * (3) FLASH_KEYR 完成 + * (4) FLASH_OPTKEYR 完成 + * (5) FLASH_SR 完成 + * (6) FLASH_CR 完成 + * (7) FLASH_ECCR 完成 + * (8) FLASH_OPTR 未完成 + * (9) FLASH_PCROP1SR 未完成 + * 后续寄存器 均未完成 + * 3. Information block + * - System memory + * - OTP area + * - Option bytes + * 4. 根据 HAL 库的实现,相比于与手册的推荐流程,擦写的执行序列还有其他操作。 + * + * 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. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "flash.h" +#include "stm32l4xx_ll_rcc.h" +#include "stm32l4xx_ll_system.h" +#include "stm32l4xx_ll_pwr.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#define WHILE_MAX 10000U +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +/** @addtogroup FLASH_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup FLASH_LL_Private_Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup FLASH_LL_Private_Macros + * @{ + */ + +#define IS_LL_FLASH_WRITE_ADDR(__ADDR__) ((__ADDR__) % LL_FLASH_ALIGNMENT_MIN_SIZE == 0) + +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup FLASH_LL_Private_Functions FLASH Private functions + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASH_LL_Exported_Functions + * @{ + */ +/** + * @brief Clear All Error in SR + * @param FLASHx FLASH Instance + * @retval None + */ +void LL_FLASH_ClearAllErrorFlag(void) +{ + LL_FLASH_ClearFlag_OPTVERR(FLASH); + LL_FLASH_ClearFlag_RDERR(FLASH); + LL_FLASH_ClearFlag_FASTERR(FLASH); + LL_FLASH_ClearFlag_MISERR(FLASH); + LL_FLASH_ClearFlag_PGSERR(FLASH); + LL_FLASH_ClearFlag_SIZERR(FLASH); + LL_FLASH_ClearFlag_PGAERR(FLASH); + LL_FLASH_ClearFlag_WRPERR(FLASH); + LL_FLASH_ClearFlag_PROGERR(FLASH); + LL_FLASH_ClearFlag_OPERR(FLASH); +} + +/** + * @brief Flush the instruction and data caches. + * @retval None + */ +void LL_FLASH_FlushCaches(void) +{ + /* Flush instruction cache */ + if (LL_FLASH_IsEnabledInstructionCache(FLASH)) + { + LL_FLASH_DisableInstructionCache(FLASH); + /* Reset instruction cache */ + LL_FLASH_InstructionCacheReset(FLASH); + /* Enable instruction cache */ + LL_FLASH_EnableInstructionCache(FLASH); + } + + /* Flush data cache */ + if (LL_FLASH_IsEnabledDataCache(FLASH)) + { + LL_FLASH_ZCS_DisableDataCache(FLASH); + /* Reset data cache */ + LL_FLASH_DataCacheReset(FLASH); + /* Enable data cache */ + LL_FLASH_ZCS_EnableDataCache(FLASH); + } +} + +/** + * @brief Erase Page + * @param pageno Page number + * @retval None + */ +ErrorStatus LL_FLASH_ErasePage(uint32_t pageno) +{ + uint16_t count = 0; + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */ + LL_FLASH_ClearAllErrorFlag(); + + /* Set the PER bit and select the page you wish to erase (PNB) with the associated bank (BKER) in the Flash control register (FLASH_CR). */ + LL_FLASH_EnablePageErase(FLASH); + + if (pageno >= LL_FLASH_BANK1_PAGE_NUM) + { + pageno -= LL_FLASH_BANK1_PAGE_NUM; + LL_FLASH_SetErasePageBank(FLASH, LL_FLASH_BANK2); + } + else + { + LL_FLASH_SetErasePageBank(FLASH, LL_FLASH_BANK1); + } + + LL_FLASH_SetErasePageNo(FLASH, pageno); + + /* Set the STRT bit in the FLASH_CR register. */ + LL_FLASH_EraseStart(FLASH); + + /* Wait for the BSY bit to be cleared in the FLASH_SR register. */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* 完成只有需要清除擦除标志. */ + LL_FLASH_DisablePageErase(FLASH); + + /* Flush the caches to be sure of the data consistency */ + LL_FLASH_FlushCaches(); + + return SUCCESS; +} + +/** + * @brief Erase bank + * @param bank This parameter can be one of the following values: + * @arg @ref LL_FLASH_BANK1 + * @arg @ref LL_FLASH_BANK2 + * @retval None + */ +ErrorStatus LL_FLASH_EraseBank(uint32_t bank) +{ + uint16_t count = 0; + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */ + LL_FLASH_ClearAllErrorFlag(); + + /* Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register (FLASH_CR). + Both banks can be selected in the same operation. */ + if (bank == LL_FLASH_BANK1) + { + LL_FLASH_EnableBank1Erase(FLASH); + } + else + { + LL_FLASH_EnableBank2Erase(FLASH); + } + + /* Set the STRT bit in the FLASH_CR register. */ + LL_FLASH_EraseStart(FLASH); + + /* Wait for the BSY bit to be cleared in the FLASH_SR register. */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* 完成只有需要清除擦除标志. */ + LL_FLASH_DisableBank1Erase(FLASH); + LL_FLASH_DisableBank2Erase(FLASH); + + /* Flush the caches to be sure of the data consistency */ + LL_FLASH_FlushCaches(); + return SUCCESS; +} + +/** + * @brief Erase Chip + * @param None + * @retval None + */ +ErrorStatus LL_FLASH_EraseChip(void) +{ + uint16_t count = 0; + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */ + LL_FLASH_ClearAllErrorFlag(); + + /* Set the MER1 bit or/and MER2 (depending on the bank) in the Flash control register (FLASH_CR). + Both banks can be selected in the same operation. */ + LL_FLASH_EnableBank1Erase(FLASH); + LL_FLASH_EnableBank2Erase(FLASH); + + /* Set the STRT bit in the FLASH_CR register. */ + LL_FLASH_EraseStart(FLASH); + + /* Wait for the BSY bit to be cleared in the FLASH_SR register. */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* 完成只有需要清除擦除标志. */ + LL_FLASH_DisableBank1Erase(FLASH); + LL_FLASH_DisableBank2Erase(FLASH); + + /* Flush the caches to be sure of the data consistency */ + LL_FLASH_FlushCaches(); + return SUCCESS; +} + +/** + * @brief Program Double Word + * @param address specifies the address to be programmed. + * @param data specifies the data to be programmed. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Write successfully + * - ERROR: error + */ +ErrorStatus LL_FLASH_ProgramDoubleWord(uint32_t address, uint64_t data) +{ + assert_param(!IS_LL_FLASH_WRITE_ADDR(address)); + uint16_t count = 0; + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */ + LL_FLASH_ClearAllErrorFlag(); + + /* Set the PG bit in the Flash control register (FLASH_CR). */ + LL_FLASH_EnableProgram(FLASH); + + /* Perform the data write operation at the desired memory address, inside main memory + block or OTP area. Only double word can be programmed. */ + /* Program the double word */ + *(__IO uint32_t *)address = (uint32_t)data; + *(__IO uint32_t *)(address + 4U) = (uint32_t)(data >> 32); + + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + /* Check that EOP flag is set in the FLASH_SR register (meaning that the programming + operation has succeed), and clear it by software. */ + if (LL_FLASH_IsActiveFlag_EOP(FLASH)) + { + LL_FLASH_ClearFlag_EOP(FLASH); + } + + /* Clear the PG bit in the FLASH_CR register if there no more programming request anymore. */ + LL_FLASH_DisableProgram(FLASH); + + /* Flush the caches to be sure of the data consistency */ + LL_FLASH_FlushCaches(); + + return SUCCESS; +} + +/** + * @brief Program + * @param address specifies the address to be programmed. + * @param data specifies the data to be programmed. + * @param num specifies the data number + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Write successfully + * - ERROR: error + */ +ErrorStatus LL_FLASH_Program(uint32_t address, uint8_t data[], uint32_t num) +{ + static uint64_t DataT = 0; + uint32_t T = 0, S = 0; + uint16_t count = 0; + assert_param(!IS_LL_FLASH_WRITE_ADDR(address)); + + if (num == 0) + { + return SUCCESS; + } + + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + /* Check and clear all error programming flags due to a previous programming. If not, PGSERR is set. */ + LL_FLASH_ClearAllErrorFlag(); + + /* Set the PG bit in the Flash control register (FLASH_CR). */ + LL_FLASH_EnableProgram(FLASH); + + /* Perform the data write operation at the desired memory address, inside main memory + block or OTP area. Only double word can be programmed. */ + T = num; + while (num > 0) + { + DataT = 0; + if (num >= 8) + { + for (int i = 0; i < LL_FLASH_ALIGNMENT_MIN_SIZE; i++) + { + DataT = DataT << 8; + DataT |= data[S + 7 - i]; + } + S += LL_FLASH_ALIGNMENT_MIN_SIZE; + num -= LL_FLASH_ALIGNMENT_MIN_SIZE; + } + else + { + for (int i = 0; i < num; i++) + { + DataT = DataT << 8; + DataT |= data[T - 1 - i]; + } + num = 0; + } + + /* Program the double word */ + *(__IO uint32_t *)address = (uint32_t)DataT; + *(__IO uint32_t *)(address + 4U) = (uint32_t)(DataT >> 32); + + /* Check that no Flash memory operation is ongoing by checking the BSY bit */ + while (LL_FLASH_IsActiveFlag_BSY(FLASH)) + { + if (count++ > WHILE_MAX) + { + return ERROR; + } + } + count = 0; + + /* Check that EOP flag is set in the FLASH_SR register (meaning that the programming + operation has succeed), and clear it by software. */ + if (LL_FLASH_IsActiveFlag_EOP(FLASH)) + { + LL_FLASH_ClearFlag_EOP(FLASH); + } + + address += LL_FLASH_ALIGNMENT_MIN_SIZE; + } + + /* Clear the PG bit in the FLASH_CR register if there no more programming request anymore. */ + LL_FLASH_DisableProgram(FLASH); + + /* Flush the caches to be sure of the data consistency */ + LL_FLASH_FlushCaches(); + + return SUCCESS; +} + +/** + * @} + */ + +/** @addtogroup FLASH_LL_Private_Functions + * @{ + */ +/** + * @brief Fast program a row double-word (64-bit) at a specified address. + * @param address: specifies the address to be programmed. + * @param DataAddress: specifies the address where the data are stored. + * @retval None + */ +void LL_FLASH_ProgramFast(uint32_t address, uint32_t DataAddress) +{ + uint8_t row_index = (2 * LL_FLASH_ROW_SIZE); + __IO uint32_t *dest_addr = (__IO uint32_t *)address; + __IO uint32_t *src_addr = (__IO uint32_t *)DataAddress; + + /* Check the parameters */ + assert_param(IS_FLASH_MAIN_MEM_ADDRESS(address)); + + /* Set FSTPG bit */ + LL_FLASH_EnableFastProgram(FLASH); + + /* Disable interrupts to avoid any interruption during the loop */ + __disable_irq(); + + /* Program the double word of the row */ + do + { + *dest_addr = *src_addr; + dest_addr++; + src_addr++; + row_index--; + } while (row_index != 0U); + + /* Re-enable the interrupts */ + __enable_irq(); + + LL_FLASH_DisableFastProgram(FLASH); +} + +/** + * @brief Fast program a row double-word (64-bit) at a specified address. + * @param address: specifies the address to be programmed. + * @param data: specifies the data to be programmed. + * @retval None + */ +ErrorStatus LL_FLASH_Read(uint32_t address, uint8_t data[], uint32_t num) +{ + if (num == 0) + { + return SUCCESS; + } + for (uint32_t i = 0; i < num; i++) + { + data[i] = *(__IO uint8_t *)(address + i); + } + + return SUCCESS; +} + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/User/system/bsp/flash.h b/User/system/bsp/flash.h new file mode 100644 index 0000000..8051762 --- /dev/null +++ b/User/system/bsp/flash.h @@ -0,0 +1,1725 @@ +/** + * @file flash.h + * @author xxx + * @date 2024-02-07 11:49:34 + * @brief + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + * @attention + * + * ST 的官方驱动 LL 库并没有 flash 驱动。这里自己实现。 + * + * 1. 由于在 stm32l4xx_ll_system.h 中存在部分 FLASH 操作函数(ACR寄存器的处理)且不全面 + * 因此这里需要额外处理(重命名) + * + * 2. Main memory + * (1) FLASH_ACR 完成 + * (2) FLASH_PDKEYR 完成 + * (3) FLASH_KEYR 完成 + * (4) FLASH_OPTKEYR 完成 + * (5) FLASH_SR 完成 + * (6) FLASH_CR 完成 + * (7) FLASH_ECCR 完成 + * (8) FLASH_OPTR 未完成 + * (9) FLASH_PCROP1SR 未完成 + * 后续寄存器 均未完成 + * 3. Information block + * - System memory + * - OTP area + * - Option bytes + * 4. 根据 HAL 库的实现,相比于与手册的推荐流程,擦写的执行序列还有其他操作。 + * + * 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. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32L4xx_LL_FLASH_H +#define __STM32L4xx_LL_FLASH_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l4xx.h" + +/** @addtogroup STM32L4xx_LL_Driver + * @{ + */ + +/** @defgroup FLASH_LL FLASH + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup FLASH_LL_Private_Constants FLASH Private Constants + * @{ + */ + +/* The following values must be written consecutively to unlock the FLASH_OPTR +register allowing option byte programming/erasing operations */ +#define LL_FLASH_OPT_KEY1 ((uint32_t)0x08192A3B) +#define LL_FLASH_OPT_KEY2 ((uint32_t)0x4C5D6E7F) + +/* The following values must be written consecutively to unlock the FLASH_CR +register allowing flash programming/erasing operations */ +#define LL_FLASH_KEY1 ((uint32_t)0x45670123) +#define LL_FLASH_KEY2 ((uint32_t)0xCDEF89AB) + +/* The following values must be written consecutively to unlock the RUN_PD bit in +FLASH_ACR */ +#define LL_FLASH_PDKEY1 ((uint32_t)0x04152637) +#define LL_FLASH_PDKEY2 ((uint32_t)0xFAFBFCFD) + +/* Page size */ +#define LL_FLASH_PAGE_SIZE (2 * 1024) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FLASH_LL_Private_Macros FLASH Private Macros + * @{ + */ +/** + * @} + */ +/* Exported types ------------------------------------------------------------*/ +/** @defgroup FLASH_LL_ES_INIT FLASH Exported structures + * @{ + */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FLASH_LL_Exported_Constants FLASH Exported Constants + * @{ + */ + +/** @defgroup FLASH_LL_EC_BANK bank + * @{ + */ +#define LL_FLASH_BANK1 0 /*!< bank 1 */ +#define LL_FLASH_BANK2 1 /*!< bank 2 */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_ALIGNMENT alignment + * @{ + */ +#define LL_FLASH_ALIGNMENT_MIN_SIZE 8 /*!< the min alignment size */ +#define LL_FLASH_ROW_SIZE 32 /* row (32 double word) */ +#define LL_FLASH_BANK1_PAGE_NUM 256 /* */ +#define LL_FLASH_BANK2_PAGE_NUM 256 /* */ + +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_FLASH_ReadReg function. + * @{ + */ +#define LL_FLASH_SR_BSY FLASH_SR_BSY /*!< Busy flag */ +#define LL_FLASH_SR_OPTVERR FLASH_SR_OPTVERR /*!< Option validity error flag */ +#define LL_FLASH_SR_RDERR FLASH_SR_RDERR /*!< PCROP read error flag */ +#define LL_FLASH_SR_FASTERR FLASH_SR_FASTERR /*!< Fast programming error flag */ +#define LL_FLASH_SR_MISERR FLASH_SR_MISERR /*!< Fast programming data miss error flag */ +#define LL_FLASH_SR_PGSERR FLASH_SR_PGSERR /*!< Programming sequence error flag */ +#define LL_FLASH_SR_SIZERR FLASH_SR_SIZERR /*!< Size error flag */ +#define LL_FLASH_SR_PGAERR FLASH_SR_PGAERR /*!< Programming alignment error flag */ +#define LL_FLASH_SR_WRPERR FLASH_SR_WRPERR /*!< Write protection error flag */ +#define LL_FLASH_SR_PROGERR FLASH_SR_PROGERR /*!< Programming error flag */ +#define LL_FLASH_SR_OPERR FLASH_SR_OPERR /*!< Operation error flag */ +#define LL_FLASH_SR_EOP FLASH_SR_EOP /*!< End of operation flag */ +/* */ +#define LL_FLASH_ECCR_DETECTION FLASH_ECCR_ECCD /*!< ECC detection */ +#define LL_FLASH_ECCR_CORRECTION FLASH_ECCR_ECCC /*!< ECC correction */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_FLASH_ReadReg and LL_FLASH_WriteReg functions + * @{ + */ +#define LL_FLASH_CR_RDERRIE FLASH_CR_RDERRIE /*!< PCROP read error interrupt enable */ +#define LL_FLASH_CR_ERRIE FLASH_CR_ERRIE /*!< Error interrupt enable */ +#define LL_FLASH_CR_EOPIE FLASH_CR_EOPIE /*!< End of operation interrupt enable */ +#define LL_FLASH_CR_ECCIE FLASH_ECCR_ECCIE /*!< ECC correction interrupt enable */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_Latency Flash Latency + * @{ + */ +#define LL_FLASH_LATENCY_0WS FLASH_ACR_LATENCY_0WS /*!< FLASH Zero Latency cycle */ +#define LL_FLASH_LATENCY_1WS FLASH_ACR_LATENCY_1WS /*!< FLASH One Latency cycle */ +#define LL_FLASH_LATENCY_2WS FLASH_ACR_LATENCY_2WS /*!< FLASH Two Latency cycles */ +#define LL_FLASH_LATENCY_3WS FLASH_ACR_LATENCY_3WS /*!< FLASH Three Latency cycles */ +#define LL_FLASH_LATENCY_4WS FLASH_ACR_LATENCY_4WS /*!< FLASH Four Latency cycles */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_PREFETCH Prefetch + * @{ + */ +#define LL_FLASH_PREFETCH_DISABLE 0x00000000U /*!< Prefetch disabled */ +#define LL_FLASH_PREFETCH_ENABLE FLASH_ACR_PRFTEN /*!< Prefetch enabled */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_INSTRUCTION_CACHE Instruction cache + * @{ + */ +#define LL_FLASH_INSTRUCTION_CACHE_DISABLE 0x00000000U /*!< Instruction cache disabled */ +#define LL_FLASH_INSTRUCTION_CACHE_ENABLE FLASH_ACR_ICEN /*!< Instruction cache enabled */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_DATA_CACHE data cache + * @{ + */ +#define LL_FLASH_DATA_CACHE_DISABLE 0x00000000U /*!< data cache disabled */ +#define LL_FLASH_DATA_CACHE_ENABLE FLASH_ACR_DCEN /*!< data cache enabled */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_RUN_PD_MODE Flash Power-down mode during Run or Low-power run mode + * @{ + */ +#define LL_FLASH_RUN_PD_MODE_IDLE 0x00000000U /*!< Flash in Idle mode */ +#define LL_FLASH_RUN_PD_MODE_PD FLASH_ACR_RUN_PD /*!< Flash in Power-down mode */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_SLEEP_PD_MODE Flash Power-down mode during Sleep or Low-power sleep mode + * @{ + */ +#define LL_FLASH_SLEEP_PD_MODE_IDLE 0x00000000U /*!< Flash in Idle mode during Sleep and Low-power sleep modes */ +#define LL_FLASH_SLEEP_PD_MODE_PD FLASH_ACR_SLEEP_PD /*!< Flash in Power-down mode during Sleep and Low-power sleep modes */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_PG Programming + * @{ + */ +#define LL_FLASH_PROGRAMMING_DISABLE 0x00000000U /*!< Flash programming disabled */ +#define LL_FLASH_PROGRAMMING_ENABLE FLASH_CR_PG /*!< Flash programming enabled */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_PER Programming + * @{ + */ +#define LL_FLASH_PAGE_ERASE_DISABLE 0x00000000U /*!< page erase disabled */ +#define LL_FLASH_PAGE_ERASE_ENABLE FLASH_CR_PER /*!< page erase enabled */ +/** + * @} + */ + +/** @defgroup FLASH_LL_EC_OBL_LAUNCH Force the option byte loading + * @{ + */ +#define LL_FLASH_OB_LAUNCH_COMPLETE 0x00000000U /*!< Option byte loading complete */ +#define LL_FLASH_OB_LAUNCH_REQUESTED FLASH_CR_OBL_LAUNCH /*!< Option byte loading requested */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_Read_Protection FLASH Option Bytes Read Protection + * @{ + */ +#define LL_FLASH_OB_RDP_LEVEL_0 ((uint32_t)0xAA) +#define LL_FLASH_OB_RDP_LEVEL_1 ((uint32_t)0xBB) +#define LL_FLASH_OB_RDP_LEVEL_2 ((uint32_t)0xCC) /*!< Warning: When enabling read protection level 2 it's no more possible to go back to level 1 or 0 */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_BOR_LEVEL FLASH Option Bytes BOR Level + * @{ + */ +#define LL_FLASH_OB_BOR_LEVEL_0 ((uint32_t)FLASH_OPTR_BOR_LEV_0) /*!< Reset level threshold is around 1.7V */ +#define LL_FLASH_OB_BOR_LEVEL_1 ((uint32_t)FLASH_OPTR_BOR_LEV_1) /*!< Reset level threshold is around 2.0V */ +#define LL_FLASH_OB_BOR_LEVEL_2 ((uint32_t)FLASH_OPTR_BOR_LEV_2) /*!< Reset level threshold is around 2.2V */ +#define LL_FLASH_OB_BOR_LEVEL_3 ((uint32_t)FLASH_OPTR_BOR_LEV_3) /*!< Reset level threshold is around 2.5V */ +#define LL_FLASH_OB_BOR_LEVEL_4 ((uint32_t)FLASH_OPTR_BOR_LEV_4) /*!< Reset level threshold is around 2.8V */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_nRST_STOP FLASH Option Bytes Reset On Stop + * @{ + */ +#define LL_FLASH_OB_STOP_RST ((uint32_t)0x0000) /*!< Reset generated when entering the stop mode */ +#define LL_FLASH_OB_STOP_NORST ((uint32_t)FLASH_OPTR_nRST_STOP) /*!< No reset generated when entering the stop mode */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_nRST_STANDBY FLASH Option Bytes Reset On Standby + * @{ + */ +#define LL_FLASH_OB_STANDBY_RST ((uint32_t)0x0000) /*!< Reset generated when entering the standby mode */ +#define LL_FLASH_OB_STANDBY_NORST ((uint32_t)FLASH_OPTR_nRST_STDBY) /*!< No reset generated when entering the standby mode */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_nRST_SHUTDOWN FLASH Option Bytes Reset On Shutdown + * @{ + */ +#define LL_FLASH_OB_SHUTDOWN_RST ((uint32_t)0x0000) /*!< Reset generated when entering the shutdown mode */ +#define LL_FLASH_OB_SHUTDOWN_NORST ((uint32_t)FLASH_OPTR_nRST_SHDW) /*!< No reset generated when entering the shutdown mode */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_IWDG_SW FLASH Option Bytes IWDG Type + * @{ + */ +#define LL_FLASH_OB_IWDG_HW ((uint32_t)0x00000) /*!< Hardware independent watchdog */ +#define LL_FLASH_OB_IWDG_SW ((uint32_t)FLASH_OPTR_IWDG_SW) /*!< Software independent watchdog */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_IWDG_STOP FLASH Option Bytes IWDG Mode On Stop + * @{ + */ +#define LL_FLASH_OB_IWDG_STOP_FREEZE ((uint32_t)0x00000) /*!< Independent watchdog counter is frozen in Stop mode */ +#define LL_FLASH_OB_IWDG_STOP_RUN ((uint32_t)FLASH_OPTR_IWDG_STOP) /*!< Independent watchdog counter is running in Stop mode */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_IWDG_STANDBY FLASH Option Bytes IWDG Mode On Standby + * @{ + */ +#define LL_FLASH_OB_IWDG_STDBY_FREEZE ((uint32_t)0x00000) /*!< Independent watchdog counter is frozen in Standby mode */ +#define LL_FLASH_OB_IWDG_STDBY_RUN ((uint32_t)FLASH_OPTR_IWDG_STDBY) /*!< Independent watchdog counter is running in Standby mode */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_WWDG_SW FLASH Option Bytes WWDG Type + * @{ + */ +#define LL_FLASH_OB_WWDG_HW ((uint32_t)0x00000) /*!< Hardware window watchdog */ +#define LL_FLASH_OB_WWDG_SW ((uint32_t)FLASH_OPTR_WWDG_SW) /*!< Software window watchdog */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_BFB2 FLASH Option Bytes BFB2 Mode + * @{ + */ +#define LL_FLASH_OB_BFB2_DISABLE ((uint32_t)0x000000) /*!< Dual-bank boot disable */ +#define LL_FLASH_OB_BFB2_ENABLE ((uint32_t)FLASH_OPTR_BFB2) /*!< Dual-bank boot enable */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_DUALBANK FLASH Option Bytes Dual-bank Type + * @{ + */ +#define LL_FLASH_OB_DUALBANK_SINGLE ((uint32_t)0x000000) /*!< 256 KB/512 KB Single-bank Flash */ +#define LL_FLASH_OB_DUALBANK_DUAL ((uint32_t)FLASH_OPTR_DUALBANK) /*!< 256 KB/512 KB Dual-bank Flash */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_nBOOT1 FLASH Option Bytes User BOOT1 Type + * @{ + */ +#define LL_FLASH_OB_BOOT1_SRAM ((uint32_t)0x000000) /*!< Embedded SRAM1 is selected as boot space (if BOOT0=1) */ +#define LL_FLASH_OB_BOOT1_SYSTEM ((uint32_t)FLASH_OPTR_nBOOT1) /*!< System memory is selected as boot space (if BOOT0=1) */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_SRAM2_PE FLASH Option Bytes User SRAM2 Parity Check Type + * @{ + */ +#define LL_FLASH_OB_SRAM2_PARITY_ENABLE ((uint32_t)0x0000000) /*!< SRAM2 parity check enable */ +#define LL_FLASH_OB_SRAM2_PARITY_DISABLE ((uint32_t)FLASH_OPTR_SRAM2_PE) /*!< SRAM2 parity check disable */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_SRAM2_RST FLASH Option Bytes User SRAM2 Erase On Reset Type + * @{ + */ +#define LL_FLASH_OB_SRAM2_RST_ERASE ((uint32_t)0x0000000) /*!< SRAM2 erased when a system reset occurs */ +#define LL_FLASH_OB_SRAM2_RST_NOT_ERASE ((uint32_t)FLASH_OPTR_SRAM2_RST) /*!< SRAM2 is not erased when a system reset occurs */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_nSWBOOT0 FLASH Option Bytes User Software BOOT0 + * @{ + */ +#define LL_FLASH_OB_BOOT0_FROM_OB ((uint32_t)0x0000000) /*!< BOOT0 taken from the option bit nBOOT0 */ +#define LL_FLASH_OB_BOOT0_FROM_PIN ((uint32_t)FLASH_OPTR_nSWBOOT0) /*!< BOOT0 taken from PH3/BOOT0 pin */ +/** + * @} + */ + +/** @defgroup FLASH_LL_OB_nBOOT0 FLASH Option Bytes User nBOOT0 option bit + * @{ + */ +#define LL_FLASH_OB_BOOT0_RESET ((uint32_t)0x0000000) /*!< nBOOT0 = 0 */ +#define LL_FLASH_OB_BOOT0_SET ((uint32_t)FLASH_OPTR_nBOOT0) /*!< nBOOT0 = 1 */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup CRS_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in FLASH register + * @param __INSTANCE__ FLASH Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_FLASH_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in FLASH register + * @param __INSTANCE__ FLASH Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_FLASH_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) + /** + * @} + */ + + /* Exported functions --------------------------------------------------------*/ + /** @defgroup FLASH_LL_Exported_Functions FLASH Exported Functions + * @{ + */ + + /** @defgroup FLASH_LL_EF_Configuration Configuration + * @{ + */ + /** + * @brief Sets the code latency value + * @note When changing the CPU frequency, the following software sequences must be applied in + * order to tune the number of wait states needed to access the Flash memory + * @rmtoll ACR LATENCY LL_FLASH_SetLatency + * @param FLASHx Flash instance + * @param FLASH_Latency This parameter can be one of the following values: + * @arg @ref LL_FLASH_LATENCY_0WS + * @arg @ref LL_FLASH_LATENCY_1WS + * @arg @ref LL_FLASH_LATENCY_2WS + * @arg @ref LL_FLASH_LATENCY_3WS + * @arg @ref LL_FLASH_LATENCY_4WS + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ZCS_SetLatency(FLASH_TypeDef *FLASHx, uint32_t FLASH_Latency) + { + MODIFY_REG(FLASHx->ACR, FLASH_ACR_LATENCY, FLASH_Latency); + } + + /** + * @brief Sets the code latency value + * @rmtoll ACR LATENCY LL_FLASH_GetLatency + * @param FLASHx Flash instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_LATENCY_0WS + * @arg @ref LL_FLASH_LATENCY_1WS + * @arg @ref LL_FLASH_LATENCY_2WS + * @arg @ref LL_FLASH_LATENCY_3WS + * @arg @ref LL_FLASH_LATENCY_4WS + */ + __STATIC_INLINE uint32_t LL_FLASH_ZCS_GetLatency(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->ACR, FLASH_ACR_LATENCY)); + } + + /** + * @brief Enable FLASH Prefetch + * @rmtoll ACR PRFTEN LL_FLASH_EnablePrefetch + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ZCS_EnablePrefetch(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ACR, FLASH_ACR_PRFTEN); + } + + /** + * @brief Disable FLASH Prefetch + * @rmtoll ACR PRFTEN LL_FLASH_DisablePrefetch + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ZCS_DisablePrefetch(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->ACR, FLASH_ACR_PRFTEN); + } + + /** + * @brief Indicates whether the FLASH Prefetch is enabled. + * @rmtoll ACR PRFTEN LL_FLASH_IsEnabledPrefetch + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledPrefetch(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ACR, FLASH_ACR_PRFTEN) == (FLASH_ACR_PRFTEN)) ? 1UL : 0UL); + } + + /** + * @brief Enable FLASH Instruction cache + * @rmtoll ACR ICEN LL_FLASH_EnableInstructionCache + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableInstructionCache(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ACR, FLASH_ACR_ICEN); + } + + /** + * @brief Disable FLASH Instruction cache + * @rmtoll ACR ICEN LL_FLASH_DisableInstructionCache + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableInstructionCache(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->ACR, FLASH_ACR_ICEN); + } + + /** + * @brief Indicates whether the FLASH Instruction cache is enabled. + * @rmtoll ACR ICEN LL_FLASH_IsEnabledInstructionCache + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledInstructionCache(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ACR, FLASH_ACR_ICEN) == (FLASH_ACR_ICEN)) ? 1UL : 0UL); + } + + /** + * @brief Enable FLASH data cache + * @rmtoll ACR DCEN LL_FLASH_EnableDataCache + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ZCS_EnableDataCache(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ACR, FLASH_ACR_DCEN); + } + + /** + * @brief Disable FLASH data cache + * @rmtoll ACR DCEN LL_FLASH_DisableDataCache + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ZCS_DisableDataCache(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->ACR, FLASH_ACR_DCEN); + } + + /** + * @brief Indicates whether the FLASH data cache is enabled. + * @rmtoll ACR DCEN LL_FLASH_IsEnabledDataCache + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledDataCache(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ACR, FLASH_ACR_DCEN) == (FLASH_ACR_DCEN)) ? 1UL : 0UL); + } + + /** + * @brief Reset FLASH Instruction cache + * @note This bit can be written only when the instruction cache is disabled. + * @rmtoll ACR ICRST LL_FLASH_InstructionCacheReset + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_InstructionCacheReset(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ACR, FLASH_ACR_ICRST); + CLEAR_BIT(FLASHx->ACR, FLASH_ACR_ICRST); + } + + /** + * @brief Reset FLASH data cache + * @note This bit can be written only when the data cache is disabled. + * @rmtoll ACR DCRST LL_FLASH_DataCacheReset + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DataCacheReset(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ACR, FLASH_ACR_DCRST); + CLEAR_BIT(FLASHx->ACR, FLASH_ACR_DCRST); + } + + /** + * @brief Set Flash Power-down mode during Run or Low-power run mode + * @note This bit is write-protected with FLASH_PDKEYR. Call LL_FLASH_UnlockRunPowerDownMode before using this api + * @note The flash memory can be put in power-down mode only when the code is executed from RAM. + * @note The Flash must not be accessed when RUN_PD is set. + * @note he flash must not be put in power-down while a program or an erase operation is on-going. + * @rmtoll ACR RUN_PD LL_FLASH_SetRunPowerDownMode + * @param FLASHx FLASH Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_FLASH_RUN_PD_MODE_IDLE + * @arg @ref LL_FLASH_RUN_PD_MODE_PD + * @retval None + */ + __STATIC_INLINE void LL_FLASH_SetRunPowerDownMode(FLASH_TypeDef *FLASHx, uint32_t Mode) + { + MODIFY_REG(FLASHx->ACR, FLASH_ACR_RUN_PD, Mode); + } + + /** + * @brief Get Flash Power-down mode during Run or Low-power run mode + * @note This bit is write-protected with FLASH_PDKEYR. Call LL_FLASH_UnlockRunPowerDownMode before using this api + * @note The flash memory can be put in power-down mode only when the code is executed from RAM. + * @note The Flash must not be accessed when RUN_PD is set. + * @note he flash must not be put in power-down while a program or an erase operation is on-going. + * @rmtoll ACR RUN_PD LL_FLASH_GetRunPowerDownMode + * @param FLASHx FLASH Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_RUN_PD_MODE_IDLE + * @arg @ref LL_FLASH_RUN_PD_MODE_PD + */ + __STATIC_INLINE uint32_t LL_FLASH_GetRunPowerDownMode(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->ACR, FLASH_ACR_RUN_PD)); + } + + /** + * @brief Set Flash Power-down mode during Sleep or Low-power sleep mode + * @note The flash must not be put in power-down while a program or an erase operation is on-going. + * @rmtoll ACR SLEEP_PD LL_FLASH_SetSleepPowerDownMode + * @param FLASHx FLASH Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_FLASH_SLEEP_PD_MODE_IDLE + * @arg @ref LL_FLASH_SLEEP_PD_MODE_PD + * @retval None + */ + __STATIC_INLINE void LL_FLASH_SetSleepPowerDownMode(FLASH_TypeDef *FLASHx, uint32_t Mode) + { + MODIFY_REG(FLASHx->ACR, FLASH_ACR_SLEEP_PD, Mode); + } + + /** + * @brief Get Flash Power-down mode during Sleep or Low-power sleep mode + * @rmtoll ACR SLEEP_PD LL_FLASH_SetSleepPowerDownMode + * @param FLASHx FLASH Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_SLEEP_PD_MODE_IDLE + * @arg @ref LL_FLASH_SLEEP_PD_MODE_PD + */ + __STATIC_INLINE uint32_t LL_FLASH_GetSleepPowerDownMode(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->ACR, FLASH_ACR_SLEEP_PD)); + } + + /** + * @brief Unlock Power-down in Run mode + * @rmtoll PDKEYR LL_FLASH_SetSleepPowerDownMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_UnlockRunPowerDownMode(FLASH_TypeDef *FLASHx) + { + WRITE_REG(FLASHx->PDKEYR, LL_FLASH_PDKEY1); + WRITE_REG(FLASHx->PDKEYR, LL_FLASH_PDKEY2); + } + + /** + * @brief Sets Read protection level + * @rmtoll OPTR RDP LL_FLASH_SetReaProtectionLevel + * @param FLASHx Flash instance + * @param FLASH_Latency This parameter can be one of the following values: + * @arg @ref LL_FLASH_OB_RDP_LEVEL_0 + * @arg @ref LL_FLASH_OB_RDP_LEVEL_1 + * @arg @ref LL_FLASH_OB_RDP_LEVEL_2 + * @retval None + */ + __STATIC_INLINE void LL_FLASH_SetReaProtectionLevel(FLASH_TypeDef *FLASHx, uint32_t Level) + { + MODIFY_REG(FLASHx->ACR, FLASH_OPTR_RDP, Level); + } + + /** + * @brief Sets Read protection level + * @rmtoll OPTR RDP LL_FLASH_GetReaProtectionLevel + * @param FLASHx Flash instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_OB_RDP_LEVEL_0 + * @arg @ref LL_FLASH_OB_RDP_LEVEL_1 + * @arg @ref LL_FLASH_OB_RDP_LEVEL_2 + */ + __STATIC_INLINE uint32_t LL_FLASH_GetReaProtectionLevel(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->OPTR, FLASH_OPTR_RDP) >> FLASH_OPTR_RDP_Pos); + } + + /** + * @brief Sets BOR level + * @rmtoll OPTR BOR_LEV LL_FLASH_SetBORLevel + * @param FLASHx Flash instance + * @param FLASH_Latency This parameter can be one of the following values: + * @arg @ref LL_FLASH_OB_BOR_LEVEL_0 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_1 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_2 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_3 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_4 + * @retval None + */ + __STATIC_INLINE void LL_FLASH_SetBORLevel(FLASH_TypeDef *FLASHx, uint32_t Level) + { + MODIFY_REG(FLASHx->OPTR, FLASH_OPTR_BOR_LEV, Level); + } + + /** + * @brief Sets BOR level + * @rmtoll OPTR BOR_LEV LL_FLASH_GetBORLevel + * @param FLASHx Flash instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_OB_BOR_LEVEL_0 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_1 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_2 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_3 + * @arg @ref LL_FLASH_OB_BOR_LEVEL_4 + */ + __STATIC_INLINE uint32_t LL_FLASH_GetBORLevel(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->OPTR, FLASH_OPTR_BOR_LEV) >> FLASH_OPTR_BOR_LEV_Pos); + } + + /** + * @brief Enable Reset generated when entering the Stop mode + * @rmtoll OPTR nRST_STOP LL_FLASH_EnableResetStopMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableResetStopMode(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_STOP); + } + + /** + * @brief Disable Reset generated when entering the Stop mode + * @rmtoll OPTR nRST_STOP LL_FLASH_DisableResetStopMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableResetStopMode(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_STOP); + } + + /** + * @brief Indicates whether Reset generated when entering the Stop mode is enabled. + * @rmtoll OPTR nRST_STOP LL_FLASH_IsEnabledResetStopMode + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledResetStopMode(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_STOP) == (FLASH_OPTR_nRST_STOP)) ? 1UL : 0UL); + } + + /** + * @brief Enable Reset generated when entering the Standby mode + * @rmtoll OPTR nRST_STOP LL_FLASH_EnableResetStandbyMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableResetStandbyMode(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_STDBY); + } + + /** + * @brief Disable Reset generated when entering the Standby mode + * @rmtoll OPTR nRST_STOP LL_FLASH_DisableResetStandbyMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableResetStandbyMode(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_STDBY); + } + + /** + * @brief Indicates whether Reset generated when entering the Standby mode is enabled. + * @rmtoll OPTR nRST_STOP LL_FLASH_IsEnabledResetStandbyMode + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledResetStandbyMode(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_STDBY) == (FLASH_OPTR_nRST_STDBY)) ? 1UL : 0UL); + } + + /** + * @brief Enable Reset generated when entering the Shutdown mode + * @rmtoll OPTR nRST_STOP LL_FLASH_EnableResetShutdownMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableResetShutdownMode(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_SHDW); + } + + /** + * @brief Disable Reset generated when entering the Shutdown mode + * @rmtoll OPTR nRST_STOP LL_FLASH_DisableResetShutdownMode + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableResetShutdownMode(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_SHDW); + } + + /** + * @brief Indicates whether Reset generated when entering the Shutdown mode is enabled. + * @rmtoll OPTR nRST_STOP LL_FLASH_IsEnabledResetShutdownMode + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledResetShutdownMode(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->OPTR, FLASH_OPTR_nRST_SHDW) == (FLASH_OPTR_nRST_SHDW)) ? 1UL : 0UL); + } + + /** + * @} + */ + + /** @defgroup FLASH_LL_EF_Programming Programming + * @{ + */ + /** + * @brief Unlocks the FLASH control register access + * @param FLASHx Flash instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_Unlock(FLASH_TypeDef *FLASHx) + { + WRITE_REG(FLASHx->KEYR, LL_FLASH_KEY1); + WRITE_REG(FLASHx->KEYR, LL_FLASH_KEY2); + } + + /** + * @brief Locks the FLASH control register access + * @rmtoll CR LOCK LL_FLASH_Lock + * @param FLASHx Flash instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_Lock(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_LOCK); + } + + /** + * @brief Unlocks the FLASH Option control register access + * @param FLASHx Flash instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_OB_Unlock(FLASH_TypeDef *FLASHx) + { + WRITE_REG(FLASHx->OPTKEYR, LL_FLASH_OPT_KEY1); + WRITE_REG(FLASHx->OPTKEYR, LL_FLASH_OPT_KEY2); + } + + /** + * @brief Locks the FLASH Option control register access + * @rmtoll CR OPTLOCK LL_FLASH_OB_Lock + * @param FLASHx Flash instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_OB_Lock(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_OPTLOCK); + } + + /** + * @brief Getthe option byte loading + * @rmtoll CR OBL_LAUNCH LL_FLASH_OB_GetLaunch + * @param FLASHx FLASH Instance + * @retval This parameter can be one of the following values: + * @arg @ref LL_FLASH_OB_LAUNCH_COMPLETE + * @arg @ref LL_FLASH_OB_LAUNCH_REQUESTED + */ + __STATIC_INLINE uint32_t LL_FLASH_OB_GetLaunch(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH) >> FLASH_CR_OBL_LAUNCH_Pos); + } + + /** + * @brief Force the option byte loading + * @note When set to 1, this bit forces the option byte reloading. + * This bit is cleared only when the option byte loading is complete. + * @note It cannot be written if OPTLOCK is set. + * @rmtoll CR OBL_LAUNCH FLASH_OB_Launch + * @param FLASHx Flash instance + * @retval None + */ + __STATIC_INLINE void FLASH_OB_Launch(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_OBL_LAUNCH); + } + + /** + * @brief Enable FLASH Fast programming + * @rmtoll CR FSTPG LL_FLASH_EnableFastProgram + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableFastProgram(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_FSTPG); + } + + /** + * @brief Disable FLASH Fast programming + * @rmtoll CR FSTPG LL_FLASH_DisableFastProgram + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableFastProgram(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_FSTPG); + } + + /** + * @brief Indicates whether the FLASH Fast programming is enabled. + * @rmtoll CR FSTPG LL_FLASH_IsEnabledFastProgram + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledFastProgram(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_FSTPG) == (FLASH_CR_FSTPG)) ? 1UL : 0UL); + } + + /** + * @brief Enable FLASH Program + * @rmtoll CR PG LL_FLASH_EnableProgram + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableProgram(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_PG); + } + + /** + * @brief Disable FLASH Program + * @rmtoll CR PG LL_FLASH_DisableProgram + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableProgram(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_PG); + } + + /** + * @brief Indicates whether the FLASH Program is enabled. + * @rmtoll CR PRFTEN LL_FLASH_IsEnabledProgram + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledProgram(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_PG) == (FLASH_CR_PG)) ? 1UL : 0UL); + } + + /** + * @brief Set Page number MSB (bank selection) + * @rmtoll CR BKER LL_FLASH_SetErasePageBank + * @param FLASHx FLASH Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_FLASH_BANK1 + * @arg @ref LL_FLASH_BANK2 + * @retval None + */ + __STATIC_INLINE void LL_FLASH_SetErasePageBank(FLASH_TypeDef *FLASHx, uint32_t bank) + { + MODIFY_REG(FLASHx->CR, FLASH_CR_BKER, (bank << FLASH_CR_BKER_Pos)); + } + + /** + * @brief Get Page number MSB (bank selection) + * @rmtoll CR BKER LL_FLASH_GetErasePageBank + * @param FLASHx FLASH Instance + * @retval This parameter can be one of the following values: + * @arg @ref LL_FLASH_BANK1 + * @arg @ref LL_FLASH_BANK2 + */ + __STATIC_INLINE uint32_t LL_FLASH_GetErasePageBank(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->CR, FLASH_CR_BKER) >> FLASH_CR_BKER_Pos); + } + + /** + * @brief Set Page number selection + * @rmtoll CR PNB LL_FLASH_SetErasePageNo + * @param FLASHx FLASH Instance + * @param No This parameter can be one of the following values: + * @arg @ref 0 ~ 255 + * @retval None + */ + __STATIC_INLINE void LL_FLASH_SetErasePageNo(FLASH_TypeDef *FLASHx, uint32_t No) + { + MODIFY_REG(FLASHx->CR, FLASH_CR_PNB, ((No & 0xFFU) << FLASH_CR_PNB_Pos)); + } + + /** + * @brief Get Page number selection + * @rmtoll CR PNB LL_FLASH_SetErasePageNo + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE uint32_t LL_FLASH_GetErasePageNo(FLASH_TypeDef *FLASHx) + { + return (uint32_t)(READ_BIT(FLASHx->CR, FLASH_CR_PNB) >> FLASH_CR_PNB_Pos); + } + + /** + * @brief Clear Page number selection + * @rmtoll CR PNB LL_FLASH_ClearErasePageNo + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearErasePageNo(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_PNB); + } + + /** + * @brief Enable Page Erase + * @rmtoll CR PER LL_FLASH_EnablePageErase + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnablePageErase(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_PER); + } + + /** + * @brief Disable Page Erase + * @rmtoll CR PER LL_FLASH_DisablePageErase + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisablePageErase(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_PER); + } + + /** + * @brief Indicates whether the Page Erase is enabled. + * @rmtoll CR PER LL_FLASH_IsEnabledPageErase + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledPageErase(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_PER) == (FLASH_CR_PER)) ? 1UL : 0UL); + } + + /** + * @brief Enable Bank1 Erase + * @rmtoll CR MER1 LL_FLASH_EnableBank1Erase + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableBank1Erase(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_MER1); + } + + /** + * @brief Disable FLASH Bank1Erase + * @rmtoll CR MER1 LL_FLASH_DisableBank1Erase + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableBank1Erase(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_MER1); + } + + /** + * @brief Indicates whether the Bank1 Erase is enabled. + * @rmtoll CR MER1 LL_FLASH_IsEnabledBank1Erase + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledBank1Erase(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_MER1) == (FLASH_CR_MER1)) ? 1UL : 0UL); + } + + /** + * @brief Enable Bank2 Erase + * @rmtoll CR MER2 LL_FLASH_EnableBank2Erase + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableBank2Erase(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_MER2); + } + + /** + * @brief Disable Bank2 Erase + * @rmtoll CR MER2 LL_FLASH_DisableBank2Erase + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableBank2Erase(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_MER2); + } + + /** + * @brief Indicates whether the Bank2 Erase is enabled. + * @rmtoll CR MER2 LL_FLASH_IsEnabledBank2Erase + * @param FLASHx Flash instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledBank2Erase(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_MER2) == (FLASH_CR_MER2)) ? 1UL : 0UL); + } + + /** + * @brief Start an erase operation + * @note If MER1, MER2 and PER bits are reset and the STRT bit is set, + * an unpredictable behavior may occur without generating any error flag. + * This condition should be forbidden. + * @note This bit is set only by software, and is cleared when the BSY bit is cleared in FLASH_SR. + * @rmtoll CR STRT LL_FLASH_EraseStart + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EraseStart(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_STRT); + } + + /** + * @brief Start an options operation + * @note This bit is set only by software, and is cleared when the BSY bit is cleared in FLASH_SR. + * @rmtoll CR STRT LL_FLASH_OprationStart + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_OB_OprationStart(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_OPTSTRT); + } + + /** + * @brief Get ECC fail bank + * @note When ECCC or ECCD is set, ADDR_ECC and BK_ECC are not updated if a new ECC error + * occurs. FLASH_ECCR is updated only when ECC flags are cleared. + * @rmtoll ECCR BK_ECC LL_FLASH_ECC_GetFailBank + * @param FLASHx FLASH Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_FLASH_BANK1 + * @arg @ref LL_FLASH_BANK2 + */ + __STATIC_INLINE uint32_t LL_FLASH_ECC_GetFailBank(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ECCR, FLASH_ECCR_BK_ECC) == (FLASH_ECCR_BK_ECC)) ? LL_FLASH_BANK2 : LL_FLASH_BANK1); + } + + /** + * @brief Get ECC fail addr + * @note When ECCC or ECCD is set, ADDR_ECC and BK_ECC are not updated if a new ECC error + * occurs. FLASH_ECCR is updated only when ECC flags are cleared. + * @rmtoll ECCR ADDR_ECC LL_FLASH_ECC_GetFailAddr + * @param FLASHx FLASH Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x7FFFF + */ + __STATIC_INLINE uint32_t LL_FLASH_ECC_GetFailAddr(FLASH_TypeDef *FLASHx) + { + return (uint32_t)((READ_BIT(FLASHx->ECCR, FLASH_ECCR_ADDR_ECC) == (FLASH_ECCR_ADDR_ECC)) >> FLASH_ECCR_ADDR_ECC_Pos); + } + + /** + * @} + */ + + /** @defgroup FLASH_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + /** + * @brief Get Busy flag + * @note This is set on the beginning of a Flash operation + * and reset when the operation finishes or when an error occurs. + * @rmtoll FLASH_SR BSY LL_FLASH_IsActiveFlag_BSY + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_BSY(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_BSY) == (FLASH_SR_BSY)) ? 1UL : 0UL); + } + + /** + * @brief Get Option validity error flag + * @note Set by hardware when the options read may not be the one configured by the user. + If option haven’t been properly loaded, OPTVERR is set again after each system reset. + * @rmtoll FLASH_SR OPTVERR LL_FLASH_IsActiveFlag_OPTVERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_OPTVERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_OPTVERR) == (FLASH_SR_OPTVERR)) ? 1UL : 0UL); + } + + /** + * @brief Get PCROP read error flag + * @note Set by hardware when an address to be read through the D-bus belongs to a + read protected area of the flash (PCROP protection). + @note An interrupt is generated if RDERRIE is set in FLASH_CR. + * @rmtoll FLASH_SR RDERR LL_FLASH_IsActiveFlag_RDERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_RDERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_RDERR) == (FLASH_SR_RDERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Fast programming error flag + * @note Set by hardware when a fast programming sequence (activated by FSTPG) is interrupted + * due to an error (alignment, size, write protection or data miss). + * @note The corresponding status bit (PGAERR, SIZERR, WRPERR or MISSERR) is set at the same time. + * @rmtoll FLASH_SR FASTERR LL_FLASH_IsActiveFlag_FASTERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_FASTERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_FASTERR) == (FLASH_SR_FASTERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Fast programming data miss error flag + * @note In Fast programming mode, 32 double words must be sent to flash successively, + and the new data must be sent to the flash logic control before the current data is fully programmed. + @note MISSERR is set by hardware when the new data is not present in time. + * @rmtoll FLASH_SR MISERR LL_FLASH_IsActiveFlag_MISERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_MISERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_MISERR) == (FLASH_SR_MISERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Programming sequence error flag + * @note Set by hardware when a write access to the Flash memory is performed by the code + * while PG or FSTPG have not been set previously. + * @note Set also by hardware when PROGERR, SIZERR, PGAERR, MISSERR or FASTERR is set + * due to a previous programming error. + * @rmtoll FLASH_SR PGSERR LL_FLASH_IsActiveFlag_PGSERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_PGSERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_PGSERR) == (FLASH_SR_PGSERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Size error flag + * @note Set by hardware when the size of the access is a byte or half-word + * during a program or a fast program sequence. + * @note Only double word programming is allowed (consequently: word access). + * @rmtoll FLASH_SR SIZERR LL_FLASH_IsActiveFlag_SIZERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_SIZERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_SIZERR) == (FLASH_SR_SIZERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Programming alignment error flag + * @note Set by hardware when the data to program cannot be contained + * in the same 64-bit Flash memory row in case of standard programming, + * or if there is a change of page during fast programming. + * @rmtoll FLASH_SR PGAERR LL_FLASH_IsActiveFlag_PGAERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_PGAERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_PGAERR) == (FLASH_SR_PGAERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Write protection error flag + * @note Set by hardware when an address to be erased/programmed + * belongs to a write-protected part (by WRP, PCROP or RDP level 1) of the Flash memory. + * @rmtoll FLASH_SR WRPERR LL_FLASH_IsActiveFlag_WRPERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_WRPERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_WRPERR) == (FLASH_SR_WRPERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Programming error flag + * @note Set by hardware when a double-word address to be programmed contains a value + * different from '0xFFFF FFFF' before programming, except if the data to write is '0x0000 0000'. + * @rmtoll FLASH_SR PROGERR LL_FLASH_IsActiveFlag_PROGERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_PROGERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_PROGERR) == (FLASH_SR_PROGERR)) ? 1UL : 0UL); + } + + /** + * @brief Get Operation error flag + * @note Set by hardware when a Flash memory operation (program / erase) completes unsuccessfully. + * @note This bit is set only if error interrupts are enabled (ERRIE = 1). + * @rmtoll FLASH_SR OPERR LL_FLASH_IsActiveFlag_OPERR + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_OPERR(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_OPERR) == (FLASH_SR_OPERR)) ? 1UL : 0UL); + } + + /** + * @brief Get End of operation flag + * @note Set by hardware when one or more Flash memory operation (programming / erase) has been completed successfully. + * @note This bit is set only if the end of operation interrupts are enabled (EOPIE = 1). + * @rmtoll FLASH_SR EOP LL_FLASH_IsActiveFlag_EOP + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsActiveFlag_EOP(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->SR, FLASH_SR_EOP) == (FLASH_SR_EOP)) ? 1UL : 0UL); + } + + /** + * @brief Clear Internal OPTVERR flag + * @rmtoll ISR IOPTVERR LL_FLASH_ClearFlag_OPTVERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_OPTVERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_OPTVERR); + } + + /** + * @brief Clear Internal RDERR flag + * @rmtoll ISR IRDERR LL_FLASH_ClearFlag_RDERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_RDERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_RDERR); + } + + /** + * @brief Clear Internal FASTERR flag + * @rmtoll ISR IFASTERR LL_FLASH_ClearFlag_FASTERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_FASTERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_FASTERR); + } + + /** + * @brief Clear Internal MISERR flag + * @rmtoll ISR IMISERR LL_FLASH_ClearFlag_MISERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_MISERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_MISERR); + } + + /** + * @brief Clear Internal PGSERR flag + * @rmtoll ISR IPGSERR LL_FLASH_ClearFlag_PGSERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_PGSERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_PGSERR); + } + + /** + * @brief Clear Internal SIZERR flag + * @rmtoll ISR ISIZERR LL_FLASH_ClearFlag_SIZERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_SIZERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_SIZERR); + } + + /** + * @brief Clear Internal PGAERR flag + * @rmtoll ISR IPGAERR LL_FLASH_ClearFlag_PGAERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_PGAERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_PGAERR); + } + + /** + * @brief Clear Internal WRPERR flag + * @rmtoll ISR IWRPERR LL_FLASH_ClearFlag_WRPERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_WRPERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_WRPERR); + } + + /** + * @brief Clear Internal PROGERR flag + * @rmtoll ISR IPROGERR LL_FLASH_ClearFlag_PROGERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_PROGERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_PROGERR); + } + + /** + * @brief Clear Internal OPERR flag + * @rmtoll ISR IOPERR LL_FLASH_ClearFlag_OPERR + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_OPERR(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_OPERR); + } + + /** + * @brief Clear Internal EOP flag + * @rmtoll ISR IEOP LL_FLASH_ClearFlag_EOP + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ClearFlag_EOP(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->SR, FLASH_SR_EOP); + } + + /** + * @brief Get Internal ECC ECCD flag + * @note Set by hardware when two ECC errors have been detected. When this bit is set, a NMI is generated + * @rmtoll ECCR ECCD LL_FLASH_ECC_IsActiveFlag_ECCD + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_ECC_IsActiveFlag_ECCD(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ECCR, FLASH_ECCR_ECCD) == (FLASH_ECCR_ECCD)) ? 1UL : 0UL); + } + + /** + * @brief Get Internal ECC ECCC flag + * @note Set by hardware when one ECC error has been detected and corrected. + * An interrupt is generated if ECCIE is set. + * @rmtoll ECCR ECCC LL_FLASH_ECC_IsActiveFlag_ECCC + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_ECC_IsActiveFlag_ECCC(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ECCR, FLASH_ECCR_ECCC) == (FLASH_ECCR_ECCC)) ? 1UL : 0UL); + } + + /** + * @brief Clear Internal ECCD flag + * @rmtoll ECCR ECCD LL_FLASH_ECC_ClearFlag_ECCD + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ECC_ClearFlag_ECCD(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ECCR, FLASH_ECCR_ECCD); + } + + /** + * @brief Clear Internal ECCC flag + * @rmtoll ECCR ECCC LL_FLASH_ECC_ClearFlag_ECCC + * @param FLASHx FLASH Instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ECC_ClearFlag_ECCC(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ECCR, FLASH_ECCR_ECCC); + } + + /** + * @brief Get Internal System Flash ECC fail flag + * @note This bit indicates that the ECC error correction or double ECC error detection + * is located in the System Flash. + * @rmtoll ECCR SYSF_ECC LL_FLASH_ECC_IsActiveFlag_SYSF_ECC + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_ECC_IsActiveFlag_SYSF_ECC(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ECCR, FLASH_ECCR_SYSF_ECC) == (FLASH_ECCR_SYSF_ECC)) ? 1UL : 0UL); + } + + /** + * @} + */ + + /** @defgroup FLASH_LL_EF_IT_Management IT-Management + * @{ + */ + /** + * @brief Enable PCROP read error interrupt (RDERRIE). + * @rmtoll CR RDERRIE LL_FLASH_EnableIT_RDERRIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableIT_RDERRIE(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_RDERRIE); + } + + /** + * @brief Disable PCROP read error interrupt (RDERRIE). + * @rmtoll CR RDERRIE LL_FLASH_DisableIT_RDERRIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableIT_RDERRIE(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_RDERRIE); + } + + /** + * @brief Enable Error interrupt (ERRIE). + * @rmtoll CR ERRIE LL_FLASH_EnableIT_ERRIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableIT_ERRIE(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_ERRIE); + } + + /** + * @brief Disable Error interrupt (ERRIE). + * @rmtoll CR ERRIE LL_FLASH_DisableIT_ERRIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableIT_ERRIE(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_ERRIE); + } + + /** + * @brief Enable End of operation interrupt (EOPIE). + * @rmtoll CR EOPIE LL_FLASH_EnableIT_EOPIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_EnableIT_EOPIE(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->CR, FLASH_CR_EOPIE); + } + + /** + * @brief Disable End of operation interrupt (EOPIE). + * @rmtoll CR EOPIE LL_FLASH_DisableIT_EOPIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_DisableIT_EOPIE(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->CR, FLASH_CR_EOPIE); + } + + /** + * @brief Indicates whether the PCROP read error interrupt (RDERRIE) is enabled. + * @rmtoll CR2 RDERRIE LL_FLASH_IsEnabledIT_RDERRIE + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledIT_RDERRIE(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_RDERRIE) == (FLASH_CR_RDERRIE)) ? 1UL : 0UL); + } + + /** + * @brief Indicates whether the Error interrupt (ERRIE) is enabled. + * @rmtoll CR2 ERRIE LL_FLASH_IsEnabledIT_ERRIE + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledIT_ERRIE(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_ERRIE) == (FLASH_CR_ERRIE)) ? 1UL : 0UL); + } + + /** + * @brief Indicates whether the End of operation interrupt (EOPIE) is enabled. + * @rmtoll CR2 EOPIE LL_FLASH_IsEnabledIT_EOPIE + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_IsEnabledIT_EOPIE(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->CR, FLASH_CR_EOPIE) == (FLASH_CR_EOPIE)) ? 1UL : 0UL); + } + + /** + * @brief Enable ECC correction interrupt (ECCIE). + * @rmtoll ECCR ECCIE LL_FLASH_ECC_EnableIT_ECCIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ECC_EnableIT_ECCIE(FLASH_TypeDef *FLASHx) + { + SET_BIT(FLASHx->ECCR, FLASH_ECCR_ECCIE); + } + + /** + * @brief Disable ECC correction interrupt (ECCIE). + * @rmtoll ECCR ECCIE LL_FLASH_ECC_DisableIT_ECCIE + * @param FLASHx FLASH instance + * @retval None + */ + __STATIC_INLINE void LL_FLASH_ECC_DisableIT_ECCIE(FLASH_TypeDef *FLASHx) + { + CLEAR_BIT(FLASHx->ECCR, FLASH_ECCR_ECCIE); + } + + /** + * @brief Indicates whether the ECC correction interrupt (ECCIE) is enabled. + * @rmtoll ECCR RDERRIE LL_FLASH_ECC_IsEnabledIT_ECCIE + * @param FLASHx FLASH Instance + * @retval State of bit (1 or 0). + */ + __STATIC_INLINE uint32_t LL_FLASH_ECC_IsEnabledIT_ECCIE(FLASH_TypeDef *FLASHx) + { + return ((READ_BIT(FLASHx->ECCR, FLASH_ECCR_ECCIE) == (FLASH_ECCR_ECCIE)) ? 1UL : 0UL); + } + + /** + * @} + */ + + /** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + void LL_FLASH_ClearAllErrorFlag(void); + void LL_FLASH_FlushCaches(void); + ErrorStatus LL_FLASH_ErasePage(uint32_t pageno); + ErrorStatus LL_FLASH_EraseBank(uint32_t bank); + ErrorStatus LL_FLASH_EraseChip(void); + ErrorStatus LL_FLASH_ProgramDoubleWord(uint32_t address, uint64_t data); + ErrorStatus LL_FLASH_Program(uint32_t address, uint8_t data[], uint32_t num); + ErrorStatus LL_FLASH_Read(uint32_t address, uint8_t data[], uint32_t num); + void LL_FLASH_ProgramFast(uint32_t address, uint32_t DataAddress); + + /** + * @} + */ + + /** + * @} + */ + + /** + * @} + */ + + /** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32L4xx_LL_FLASH_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/User/system/bsp/gpios.c b/User/system/bsp/gpios.c new file mode 100644 index 0000000..cb59b80 --- /dev/null +++ b/User/system/bsp/gpios.c @@ -0,0 +1,76 @@ +#include "gpios.h" +#include "gpio.h" +/** + * @brief 设置GPIO引脚为高电平 + * @param {gpio_t} gpio - GPIO对象 + * @note: 用于设置指定GPIO引脚为高电平。 + */ +static void _set(gpio_t gpio) +{ + GPIO_SET(gpio.port, gpio.pin); +} + +/** + * @brief 设置GPIO引脚为低电平 + * @param {gpio_t} gpio - GPIO对象 + * @note: 用于设置指定GPIO引脚为低电平。 + */ +static void _reset(gpio_t gpio) +{ + GPIO_RESET(gpio.port, gpio.pin); +} + +/** + * @brief 切换GPIO引脚状态 + * @param {gpio_t} gpio - GPIO对象 + * @note: 用于切换指定GPIO引脚的状态,即高电平变为低电平,低电平变为高电平。 + */ +static void _toggle(gpio_t gpio) +{ + GPIO_TOGGLE(gpio.port, gpio.pin); +} + +/** + * @brief 读取GPIO引脚状态 + * @param {gpio_t} gpio - GPIO对象 + * @return {*} - GPIO引脚当前状态,即0表示低电平,1表示高电平 + * @note: 用于读取指定GPIO引脚的状态,即返回0或1。 + */ +static uint8_t _read(gpio_t gpio) +{ + return (uint8_t)GPIO_READ(gpio.port, gpio.pin); +} + +/** + * @brief 创建GPIO对象 + * @param {GPIO_TypeDef} *port - GPIO寄存器指针 + * @param {uint16_t} pin - 引脚号 + * @return {gpio_t *} - 创建的GPIO对象指针 + * @note: 用于创建一个GPIO对象,用于操作特定端口和引脚的GPIO功能。 + */ +gpio_t *gpio_create(GPIO_TypeDef *port, uint16_t pin) +{ + gpio_t *gpio = (gpio_t *)osel_mem_alloc(sizeof(gpio_t)); + DBG_ASSERT(gpio != NULL __DBG_LINE); + gpio->port = port; + gpio->pin = pin; + gpio->set = _set; + gpio->reset = _reset; + gpio->toggle = _toggle; + gpio->read = _read; + return gpio; +} + +/** + * @brief 释放GPIO对象 + * @param {gpio_t} *gpio - GPIO对象指针 + * @return {*} + * @note: 用于释放一个GPIO对象,释放后不能再使用该对象。 + */ +void gpio_free(gpio_t *gpio) +{ + if (gpio != NULL) + { + osel_mem_free(gpio); + } +} diff --git a/User/system/bsp/gpios.h b/User/system/bsp/gpios.h new file mode 100644 index 0000000..9f71165 --- /dev/null +++ b/User/system/bsp/gpios.h @@ -0,0 +1,144 @@ +/** + * @file gpios.h + * @brief Header file for GPIO configuration and control. + * + * This file contains the declarations and definitions for GPIO configuration and control functions. + * + * @author xxx + * @date 2023-12-27 14:44:03 + * @version 1.0 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ + +#ifndef __GPIOS_H__ +#define __GPIOS_H__ +#include "lib.h" +#include "main.h" +/** + * @brief Set the GPIO pin to high. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_SET(port, pin) (LL_GPIO_SetOutputPin(port, pin)) + +/** + * @brief Set the GPIO pin to low. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_RESET(port, pin) (LL_GPIO_ResetOutputPin(port, pin)) + +/** + * @brief Toggle the state of the GPIO pin. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_TOGGLE(port, pin) (LL_GPIO_TogglePin(port, pin)) + +/** + * @brief Read the state of the GPIO pin. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + * @return The state of the GPIO pin (1 if high, 0 if low). + */ +#define GPIO_READ(port, pin) (LL_GPIO_IsInputPinSet(port, pin)) + +/** + * @brief Set the GPIO pin as input. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_SET_INPUT(port, pin) (LL_GPIO_SetPinMode(port, pin, LL_GPIO_MODE_INPUT)) + +/** + * @brief Set the GPIO pin as output. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_SET_OUTPUT(port, pin) \ + do \ + { \ + LL_GPIO_SetPinMode(port, pin, LL_GPIO_MODE_OUTPUT); \ + } while (0) + +/** + * @brief Set the GPIO pin as alternate function. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_SET_ALTERNATE(port, pin) (LL_GPIO_SetPinMode(port, pin, LL_GPIO_MODE_ALTERNATE)) + +/** + * @brief Set the GPIO pin as analog. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + */ +#define GPIO_SET_ANALOG(port, pin) \ + do \ + { \ + LL_GPIO_SetPinMode(port, pin, LL_GPIO_MODE_ANALOG); \ + } while (0) + +/** + * @brief Structure representing a GPIO pin. + */ +typedef struct GPIO +{ + GPIO_TypeDef *port; // The GPIO port. + uint16_t pin; // The GPIO pin. + + /** + * @brief Set the GPIO pin to high. + * + * @param gpio The GPIO pin. + */ + void (*set)(struct GPIO gpio); + + /** + * @brief Set the GPIO pin to low. + * + * @param gpio The GPIO pin. + */ + void (*reset)(struct GPIO gpio); + + /** + * @brief Toggle the state of the GPIO pin. + * + * @param gpio The GPIO pin. + */ + void (*toggle)(struct GPIO gpio); + + /** + * @brief Read the state of the GPIO pin. + * + * @param gpio The GPIO pin. + * @return The state of the GPIO pin (1 if high, 0 if low). + */ + uint8_t (*read)(struct GPIO gpio); +} gpio_t; + +/** + * @brief Create a GPIO pin. + * + * @param port The GPIO port. + * @param pin The GPIO pin. + * @return The created GPIO pin. + */ +extern gpio_t *gpio_create(GPIO_TypeDef *port, uint16_t pin); + +/** + * @brief Free the memory allocated for a GPIO pin. + * + * @param gpio The GPIO pin to free. + */ +extern void gpio_free(gpio_t *gpio); + +#endif // __GPIOS_H__ diff --git a/User/system/bsp/i2cs.c b/User/system/bsp/i2cs.c new file mode 100644 index 0000000..25c39bc --- /dev/null +++ b/User/system/bsp/i2cs.c @@ -0,0 +1,661 @@ +#include "i2cs.h" +#include "main.h" + +static inline void delay(i2c_t *handle); // 延时函数 +static inline void _ack(i2c_t *handle); // 应答 +static inline void _nack(i2c_t *handle); // 非应答 + +/** + * @brief 启动I2C总线 + * @param {i2c_t} *handle - I2C总线句柄 + * @note: 用于启动I2C总线的操作。在发送或接收数据之前,需要先启动总线。 + */ +static void _start(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + // 获取gpios指针 + i2c_gpio_group_t *gpios = &handle->gpios; + // 获取scl指针 + gpio_t *scl = gpios->scl; + // 获取sda指针 + gpio_t *sda = gpios->sda; + // 设置sda + gpios->sda->set(*sda); + // 设置scl + gpios->scl->set(*scl); + // 延时 + delay(handle); + // 重置sda + gpios->sda->reset(*sda); + // 延时 + delay(handle); + // 重置scl + gpios->scl->reset(*scl); + // 延时 + delay(handle); +} + +/** + * @brief 停止I2C总线 + * @param {i2c_t} *handle - I2C总线句柄 + * @note: 用于停止I2C总线的操作。在发送或接收数据之后,需要先停止总线。 + */ +static void _stop(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + i2c_gpio_group_t *gpios = &handle->gpios; + gpio_t *scl = gpios->scl; + gpio_t *sda = gpios->sda; + gpios->scl->reset(*scl); + gpios->sda->reset(*sda); + delay(handle); + gpios->scl->set(*scl); + gpios->sda->set(*sda); + delay(handle); +} +/** + * @brief 等待应答信号 + * @param {i2c_t} *handle - I2C总线句柄 + * @return {BOOL} - 等待成功返回TRUE,否则返回FALSE + * @note: 用于等待I2C总线上发送的应答信号。 + */ +static BOOL _wait_ack(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + uint8_t count = 0; + i2c_gpio_group_t *gpios = &handle->gpios; + gpio_t *scl = gpios->scl; + gpio_t *sda = gpios->sda; + gpios->sda->set(*sda); + gpios->scl->set(*scl); + delay(handle); + while (gpios->sda->read(*sda)) + { + count++; + if (count > 250) + { + _stop(handle); + return FALSE; + } + } + gpios->scl->reset(*scl); + delay(handle); + return TRUE; +} + +/** + * @brief 读取一个字节 + * @param {i2c_t} *handle - I2C总线句柄 + * @param {BOOL} ack - 应答信号标志 + * @return {uint8_t} - 读取到的字节 + * @note: 用于从I2C总线上读取一个字节。在读取一个字节后,需要发送应答信号。 + */ +static uint8_t _read_byte(i2c_t *handle, BOOL ack) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + uint8_t i = 0, receive = 0; + i2c_gpio_group_t *gpios = &handle->gpios; + gpio_t *scl = gpios->scl; + gpio_t *sda = gpios->sda; + for (i = 0; i < 8; i++) + { + gpios->sda->set(*sda); + gpios->scl->set(*scl); + receive <<= 1; + delay(handle); + + if (gpios->sda->read(*sda)) + receive++; + + gpios->scl->reset(*scl); + delay(handle); + } + + if (TRUE == ack) + { + _ack(handle); + } + else + { + _nack(handle); + } + return receive; +} +/** + * @brief 发送一个字节的数据到I2C总线上 + * @param {i2c_t} *handle I2C总线的句柄 + * @param {uint8_t} data 要发送的字节数据 + * @return {*} 无 + * @note: 该函数用于在I2C总线上发送一个字节的数据。它首先定义了一个循环,用于遍历要发送的字节中的每一位。在循环中,首先检查当前位是否为1,如果是,则设置SDA为1,否则设置SDA为0。然后设置SCL为1,延时1ms。接着将数据右移一位,然后设置SCL为0,延时1ms。当位遍历完后,最后设置SDA为1,以确保正确的结束传输。 + */ +static void _write_byte(i2c_t *handle, uint8_t data) +{ + // 定义变量i + uint8_t i = 0; + // 断言参数handle不为空 + DBG_ASSERT(handle != NULL __DBG_LINE); + // 定义变量gpios + i2c_gpio_group_t *gpios = &handle->gpios; + // 定义变量scl + gpio_t *scl = gpios->scl; + // 定义变量sda + gpio_t *sda = gpios->sda; + // 遍历每一位 + for (i = 0; i < 8; i++) + { + // 如果data的最低位为1 + if (data & 0x80) + { + // 设置sda的状态为1 + gpios->sda->set(*sda); + } + // 否则,设置sda的状态为0 + else + { + // 设置sda的状态为0 + gpios->sda->reset(*sda); + } + + // 设置scl的状态为1 + gpios->scl->set(*scl); + // 延时1ms + delay(handle); + // 将data右移1位 + data <<= 1; + // 设置scl的状态为0 + gpios->scl->reset(*scl); + // 延时1ms + delay(handle); + + // 如果i等于7 + if (i == 7) + { + // 设置sda的状态为1 + gpios->sda->set(*sda); + } + } +} + +/** + * @brief 发送一个字节的数据到I2C总线上 + * @param {i2c_t} *handle I2C总线的句柄 + * @param {uint16_t} data 要发送的字节数据 + * @return {*} 无 + * @note: 该函数用于在I2C总线上发送一个字节的数据。它首先定义了一个循环,用于遍历要发送的字节中的每一位。在循环中,首先检查当前位是否为1,如果是,则设置SDA为1,否则设置SDA为0。然后设置SCL为1,延时1ms。接着将数据右移一位,然后设置SCL为0,延时1ms。当位遍历完后,最后设置SDA为1,以确保正确的结束传输。 + */ +static void _write_word(i2c_t *handle, uint16_t data) +{ + // 循环写入2个字节 + for (uint8_t i = 0; i < 2; i++) + { + // 将data的第i个字节写入i2c接口 + _write_byte(handle, (uint8_t)(data >> (8 * i))); + // 等待ACK + _wait_ack(handle); + } +} + +/** + * @brief I2C重置 + * @param {I2C_TypeDef} *I2Cx + * @return {*} + * @note + */ +static void i2c_reset(I2C_TypeDef *I2Cx) +{ + // Disable the I2C peripheral + LL_I2C_Disable(I2Cx); + + // Re-enable the I2C peripheral + LL_I2C_Enable(I2Cx); +} + +/** + * @brief 非阻塞模式下使用DMA将数据写入特定内存地址 + * @param {i2c_t} *handle 指向一个i2c_t结构体,其中包含指定I2C的配置信息 + * @param {uint16_t} dev_address 目标设备地址:在数据手册中,设备7位地址值需要向左移动以调用接口 + * @param {uint16_t} mem_address 内部内存地址 + * @param {uint16_t} mem_addsize 内部内存地址大小 + * @param {uint8_t} *data 数据缓冲区的指针 + * @param {uint16_t} size 要发送的数据量 + * @return {*} + * @note + */ +static BOOL _write_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + DBG_ASSERT(data != NULL __DBG_LINE); + if (LL_I2C_IsActiveFlag_BUSY(handle->i2c) == 1) + { + i2c_reset(handle->i2c); // xsh:重置I2C,修复一段时间后无法读写的问题 + } + uint16_t count = 2000; + handle->txsize = 0; + handle->tx_dma_ok = FALSE; + for (uint8_t i = mem_addsize; i > 0; i--) + { + handle->txbuf[handle->txsize++] = (uint8_t)(mem_address >> (8 * (i - 1))); + } + osel_memcpy(&handle->txbuf[handle->txsize], data, size); + handle->txsize += size; + LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, handle->txsize); + LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel); + + LL_I2C_HandleTransfer(handle->i2c, handle->w_address, LL_I2C_ADDRSLAVE_7BIT, handle->txsize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE); + + count = 2000; + while (!handle->tx_dma_ok) + { + if (count-- == 0) + { + handle->tx_dma_ok = TRUE; + return FALSE; + } + } + count = 2000; + while (!LL_I2C_IsActiveFlag_STOP(handle->i2c)) + { + if (count-- == 0) + { + handle->tx_dma_ok = TRUE; + return FALSE; + } + } + + LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel); + LL_I2C_ClearFlag_STOP(handle->i2c); + + return TRUE; +} + +/** + * @brief 非阻塞模式下使用DMA从特定内存地址读取数据 + * @param {i2c_t} *handle 指向一个i2c_t结构体,其中包含指定I2C的配置信息 + * @param {uint16_t} dev_address 目标设备地址:在数据手册中,设备7位地址值需要向左移动以调用接口 + * @param {uint16_t} mem_address 内部内存地址 + * @param {uint16_t} mem_addsize 内部内存地址大小 + * @param {uint8_t} *data 数据缓冲区的指针 + * @param {uint16_t} size 要发送的数据量 + * @return {*} + * @note + */ +static BOOL _read_mem_dma(i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + DBG_ASSERT(data != NULL __DBG_LINE); + if (LL_I2C_IsActiveFlag_BUSY(handle->i2c) == 1) + { + i2c_reset(handle->i2c); // xsh:重置I2C,修复一段时间后无法读写的问题 + } + uint16_t count = 2000; + handle->txsize = 0; + handle->tx_dma_ok = FALSE; + handle->rx_dma_ok = FALSE; + + for (uint8_t i = mem_addsize; i > 0; i--) + { + handle->txbuf[handle->txsize++] = (uint8_t)(mem_address >> (8 * (i - 1))); + } + + LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, handle->txsize); + LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel); + + LL_I2C_HandleTransfer(handle->i2c, handle->w_address, LL_I2C_ADDRSLAVE_7BIT, handle->txsize, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE); + count = 2000; + while (!handle->tx_dma_ok) + { + if (count-- == 0) + { + handle->tx_dma_ok = TRUE; + return FALSE; + } + } + + count = 2000; + while (LL_I2C_IsActiveFlag_TC(handle->i2c) != 1) + { + if (count-- == 0) + { + handle->tx_dma_ok = TRUE; + return FALSE; + } + } + + handle->tx_dma_ok = FALSE; + handle->rx_dma_ok = FALSE; + handle->rxsize = size; + osel_memset(handle->rxbuf, 0, handle->rxsize); + LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel); + LL_DMA_SetDataLength(handle->dma, handle->dma_rx_channel, handle->rxsize); + LL_DMA_EnableChannel(handle->dma, handle->dma_rx_channel); + LL_I2C_HandleTransfer(handle->i2c, handle->r_address, LL_I2C_ADDRSLAVE_7BIT, handle->rxsize, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ); + + count = 2000; + while (!LL_I2C_IsActiveFlag_STOP(handle->i2c)) + { + if (count-- == 0) + { + handle->tx_dma_ok = TRUE; + return FALSE; + } + } + + LL_DMA_DisableChannel(handle->dma, handle->dma_rx_channel); + LL_I2C_ClearFlag_STOP(handle->i2c); + osel_memcpy(data, handle->rxbuf, handle->rxsize); + return TRUE; +} +/** + * @brief 创建一个I2C总线设备 + * @param {i2c_gpio_group_t} gpios I2C总线的GPIO配置 + * @param {uint16_t} delay_ticks I2C总线的延时参数 + * @return {i2c_t *} 创建的I2C总线设备句柄 + * @note: 该函数用于创建一个I2C总线设备。它首先创建一个i2c_t结构体,并将gpios和delay_ticks的内存地址复制到handle结构体中。然后,它为handle结构体定义了start、stop、wait_ack、read_byte、write_byte和write_word函数。最后,它返回handle结构体。 + */ +i2c_t *i2c_create(i2c_gpio_group_t gpios, uint16_t delay_ticks) +{ + // 创建一个i2c_t结构体 + i2c_t *handle = (i2c_t *)osel_mem_alloc(sizeof(i2c_t)); + // 将gpios的内存地址复制到handle结构体中 + osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(i2c_gpio_group_t)); + // 将delay_ticks的内存地址复制到handle结构体中 + handle->delay_ticks = delay_ticks; + + // 创建一个start函数 + handle->interface.start = _start; + // 创建一个stop函数 + handle->interface.stop = _stop; + // 创建一个wait_ack函数 + handle->interface.wait_ack = _wait_ack; + // 创建一个read_byte函数 + handle->interface.read_byte = _read_byte; + // 创建一个write_byte函数 + handle->interface.write_byte = _write_byte; + // 创建一个write_word函数 + handle->interface.write_word = _write_word; + + // 返回handle结构体 + return handle; +} + +/** + * @brief 创建一个I2C总线设备 DMA + * @param {I2C_TypeDef} *i2c + * @param {DMA_TypeDef} *dma + * @param {uint16_t} rxsize + * @param {uint32_t} dma_rx_channel + * @param {uint16_t} txsize + * @param {uint32_t} dma_tx_channel + * @return {*} + * @note + */ +i2c_t *i2c_create_dma(I2C_TypeDef *i2c, DMA_TypeDef *dma, uint16_t rxsize, uint32_t dma_rx_channel, + i2cs_dma_callback *dma_rx_cb, uint16_t txsize, uint32_t dma_tx_channel, i2cs_dma_callback *dma_tx_cb) +{ + i2c_t *handle = (i2c_t *)osel_mem_alloc(sizeof(i2c_t)); + handle->i2c = i2c; + handle->dma = dma; + handle->dma_rx_channel = dma_rx_channel; + handle->dma_tx_channel = dma_tx_channel; + handle->rxbuf = (uint8_t *)osel_mem_alloc(rxsize); + handle->txbuf = (uint8_t *)osel_mem_alloc(txsize); + handle->rxsize = rxsize; + handle->txsize = txsize; + handle->tx_dma_ok = TRUE; + handle->interface.write_mem_dma = _write_mem_dma; + handle->interface.read_mem_dma = _read_mem_dma; + if (dma_rx_cb != NULL) + { + handle->dma_rx_cb = dma_rx_cb; + } + + if (dma_tx_cb != NULL) + { + handle->dma_tx_cb = dma_tx_cb; + } + + LL_DMA_DisableChannel(dma, dma_tx_channel); + LL_DMA_DisableChannel(dma, dma_rx_channel); + + // TX + uint8_t *pTransmitBuffer = handle->txbuf; + LL_DMA_ConfigTransfer(dma, dma_tx_channel, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE); + LL_DMA_ConfigAddresses(dma, dma_tx_channel, (uint32_t)pTransmitBuffer, (uint32_t)LL_I2C_DMA_GetRegAddr(i2c, LL_I2C_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(dma, dma_tx_channel)); + LL_DMA_SetPeriphRequest(dma, dma_tx_channel, LL_DMA_REQUEST_3); + + // RX + uint8_t *pReceiveBuffer = handle->rxbuf; + LL_DMA_ConfigTransfer(dma, dma_rx_channel, LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE); + LL_DMA_ConfigAddresses(dma, dma_rx_channel, (uint32_t)LL_I2C_DMA_GetRegAddr(i2c, LL_I2C_DMA_REG_DATA_RECEIVE), (uint32_t)pReceiveBuffer, LL_DMA_GetDataTransferDirection(dma, dma_rx_channel)); + LL_DMA_SetPeriphRequest(dma, dma_rx_channel, LL_DMA_REQUEST_3); + + LL_DMA_EnableIT_TC(dma, dma_tx_channel); + LL_DMA_EnableIT_TE(dma, dma_tx_channel); + LL_DMA_EnableIT_TC(dma, dma_rx_channel); + LL_DMA_EnableIT_TE(dma, dma_rx_channel); + + LL_I2C_EnableDMAReq_TX(i2c); + LL_I2C_EnableDMAReq_RX(i2c); + LL_I2C_Enable(i2c); + + return handle; +} + +/** + * @brief 设置I2C器件地址 + * @param {i2c_t} *handle + * @param {uint8_t} w_address 写地址 + * @param {uint8_t} r_address 读地址 + * @return {*} + * @note + */ +void i2c_dma_set_address(i2c_t *handle, uint8_t w_address, uint8_t r_address) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->w_address = w_address; + handle->r_address = r_address; +} + +/** + * @brief 释放I2C总线设备 + * @param {i2c_t} *handle 需要释放的I2C总线设备句柄 + * @return {*} 无 + * @note: 该函数用于释放一个I2C总线设备。它首先检查handle是否为空,如果不为空,则释放所有的GPIO。最后,释放handle的内存。 + */ +void i2c_free(i2c_t *handle) +{ + // 如果handle不为空,则释放所有的gpio + if (NULL != handle) + { + gpio_free(handle->gpios.scl); + gpio_free(handle->gpios.sda); + osel_mem_free(handle); + } +} + +/** + * @brief I2C DMA TX回调函数 + * @param {i2c_t} handle + * @return {*} + * @note + */ +void i2c_dma_callback(i2c_t *handle) +{ + // 检查输入参数是否为空 + DBG_ASSERT(handle != NULL __DBG_LINE); + // 清除传输完成标志位 + if (handle->dma_tx_cb != NULL) + { + handle->dma_tx_cb(handle); + } + if (handle->dma_rx_cb != NULL) + { + handle->dma_rx_cb(handle); + } +} + +/** + * @brief I2C 中断回调函数 + * @param {i2c_t} *handle + * @return {*} + * @note + */ +void i2c_ev_callback(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + if (LL_I2C_IsActiveFlag_ADDR(handle->i2c)) + { + /* Verify the Address Match with the OWN Slave address */ + if (LL_I2C_GetAddressMatchCode(handle->i2c) == handle->w_address || LL_I2C_GetAddressMatchCode(handle->i2c) == handle->r_address) + { + /* Verify the transfer direction, a write direction, Slave enters receiver mode */ + if (LL_I2C_GetTransferDirection(handle->i2c) == LL_I2C_DIRECTION_WRITE) + { + /* Clear ADDR flag value in ISR register */ + LL_I2C_ClearFlag_ADDR(handle->i2c); + + /* Enable Receive Interrupt */ + LL_I2C_EnableIT_RX(handle->i2c); + } + else if (LL_I2C_GetTransferDirection(handle->i2c) == LL_I2C_DIRECTION_READ) + { + /* Clear ADDR flag value in ISR register */ + LL_I2C_ClearFlag_ADDR(handle->i2c); + + /* Enable Transmit Interrupt */ + LL_I2C_EnableIT_TX(handle->i2c); + } + } + else + { + /* Clear ADDR flag value in ISR register */ + LL_I2C_ClearFlag_ADDR(handle->i2c); + + /* Call Error function */ + DBG_ASSERT(FALSE __DBG_LINE); + } + } + /* Check NACK flag value in ISR register */ + else if (LL_I2C_IsActiveFlag_NACK(handle->i2c)) + { + /* End of Transfer */ + LL_I2C_ClearFlag_NACK(handle->i2c); + } + /* Check RXNE flag value in ISR register */ + else if (LL_I2C_IsActiveFlag_RXNE(handle->i2c)) + { + /* Call function Slave Reception Callback */ + } + /* Check TXIS flag value in ISR register */ + else if (LL_I2C_IsActiveFlag_TXIS(handle->i2c)) + { + /* Call function Slave Ready to Transmit Callback */ + } + /* Check STOP flag value in ISR register */ + else if (LL_I2C_IsActiveFlag_STOP(handle->i2c)) + { + /* End of Transfer */ + LL_I2C_ClearFlag_STOP(handle->i2c); + + /* Check TXE flag value in ISR register */ + if (!LL_I2C_IsActiveFlag_TXE(handle->i2c)) + { + /* Flush TX buffer */ + LL_I2C_ClearFlag_TXE(handle->i2c); + } + + /* Call function Slave Complete Callback */ + } + /* Check TXE flag value in ISR register */ + else if (!LL_I2C_IsActiveFlag_TXE(handle->i2c)) + { + /* Do nothing */ + /* This Flag will be set by hardware when the TXDR register is empty */ + /* If needed, use LL_I2C_ClearFlag_TXE() interface to flush the TXDR register */ + } + else + { + /* Call Error function */ + DBG_ASSERT(FALSE __DBG_LINE); + } +} + +/*下面是内部实现方法*/ + +/** + * @brief 此方法是一个简单的延迟函数,它使用循环来执行指定数量的NOP(无操作)指令。这个延迟函数的目的是在程序的执行中引入延迟,这在需要精确定时的某些应用中很有用。延迟时间由输入参数“count”的值决定,该参数指定要执行的NOP指令的数量。延迟时间通常以微秒或毫秒为单位测量,具体取决于使用延迟的环境。 + * @param {uint16_t} count NOP指令的数量 + * @return {*} + */ +static inline void delay(i2c_t *handle) +{ + // 断言参数handle不为空 + DBG_ASSERT(handle != NULL __DBG_LINE); + // 定义循环计数变量count + uint16_t count = 0; + // 设置循环计数变量count的值为handle->delay_ticks + count = handle->delay_ticks; + // 循环计数变量count的值,直到count的值为0 + while (count--) + { + // 每次循环调用__NOP()函数 + __NOP(); + } +} + +/** + * @brief 发送ACK信号 + * @param {i2c_t} *handle I2C总线的句柄 + * @return {*} 无 + * @note: 该函数用于在I2C总线上发送ACK信号。它首先断言handle不为空,然后获取gpios和scl、sda的指针。接着重置sda,延时1ms,设置scl为1,延时1ms,重置scl,确保正确的结束传输。 + */ +static inline void _ack(i2c_t *handle) +{ + // 断言handle不为空 + DBG_ASSERT(handle != NULL __DBG_LINE); + // 获取gpios指针 + i2c_gpio_group_t *gpios = &handle->gpios; + // 获取scl指针 + gpio_t *scl = gpios->scl; + // 获取sda指针 + gpio_t *sda = gpios->sda; + + // 重置sda + gpios->sda->reset(*sda); + // 延时 + delay(handle); + // 设置scl + gpios->scl->set(*scl); + // 延时 + delay(handle); + // 重置scl + gpios->scl->reset(*scl); +} + +/** + * @brief 发送NACK信号 + * @param {i2c_t} *handle I2C总线的句柄 + * @return {*} 无 + * @note: 该函数用于在I2C总线上发送NACK信号。它首先断言handle不为空,然后获取gpios和scl、sda的指针。接着设置sda为1,延时1ms,设置scl为1,延时1ms,重置scl,确保正确的结束传输。 + */ +static inline void _nack(i2c_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + // 获取gpios指针 + i2c_gpio_group_t *gpios = &handle->gpios; + // 获取scl指针 + gpio_t *scl = gpios->scl; + // 获取sda指针 + gpio_t *sda = gpios->sda; + + // 设置sda引脚 + gpios->sda->set(*sda); + // 等待延时 + delay(handle); + // 设置scl引脚 + gpios->scl->set(*scl); + // 等待延时 + delay(handle); + // 重置scl引脚 + gpios->scl->reset(*scl); +} diff --git a/User/system/bsp/i2cs.h b/User/system/bsp/i2cs.h new file mode 100644 index 0000000..cb2e675 --- /dev/null +++ b/User/system/bsp/i2cs.h @@ -0,0 +1,126 @@ +/** + * @file i2cs.h + * @brief Header file for I2C Slave module. + * + * This file contains the declarations and definitions for the I2C Slave module. + * It provides functions to initialize and configure the I2C peripheral as a slave, + * as well as functions to send and receive data over the I2C bus. + * + * @author xxx + * @date 2023-12-27 14:44:03 + * @version 1.0 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ + +#ifndef __I2CS_H__ +#define __I2CS_H__ +#include "lib.h" +#include "gpios.h" +/** + * @file i2cs.h + * @brief Header file containing the definition of the I2C slave (I2CS) structure and related functions. + */ + +typedef struct I2CS i2c_t; +typedef void i2cs_dma_callback(i2c_t *handle); + +typedef struct +{ + void (*start)(i2c_t *handle); // Function pointer to start the I2C communication. + void (*stop)(i2c_t *handle); // Function pointer to stop the I2C communication. + BOOL(*wait_ack) + (i2c_t *handle); // Function pointer to wait for the acknowledgment from the I2C bus. + + void (*write_byte)(i2c_t *handle, uint8_t data); // Function pointer to write a byte of data to the I2C bus. + uint8_t (*read_byte)(i2c_t *handle, BOOL ack); // Function pointer to read a byte of data from the I2C bus. + + void (*write_word)(i2c_t *handle, uint16_t data); // Function pointer to write two bytes of data to the I2C bus. + + BOOL(*write_mem_dma) + (i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); // Function pointer to write multiple bytes of data to a memory address using DMA. + BOOL(*read_mem_dma) + (i2c_t *handle, uint16_t mem_address, uint16_t mem_addsize, uint8_t *data, uint16_t size); // Function pointer to read multiple bytes of data from a memory address using DMA. +} i2c_interface_t; + +typedef struct +{ + struct GPIO *scl; // Pointer to the GPIO pin used for the I2C clock (SCL). + struct GPIO *sda; // Pointer to the GPIO pin used for the I2C data (SDA). +} i2c_gpio_group_t; + +struct I2CS +{ + // Analog part definition + i2c_gpio_group_t gpios; // Structure containing the GPIO pins used for the I2C communication. + uint16_t delay_ticks; // Number of NOP instructions to delay the I2C communication. + + // Hardware part definition + I2C_TypeDef *i2c; // Pointer to the I2C peripheral. + DMA_TypeDef *dma; // Pointer to the DMA peripheral. + uint32_t dma_rx_channel; // DMA channel used for receiving data. + uint32_t dma_tx_channel; // DMA channel used for transmitting data. + uint8_t *rxbuf; // Pointer to the receive buffer. + uint16_t rxsize; // Size of the receive buffer. + uint8_t *txbuf; // Pointer to the transmit buffer. + uint16_t txsize; // Size of the transmit buffer. + uint8_t w_address; // 7-bit write address. + uint8_t r_address; // 7-bit read address. + __IO BOOL rx_dma_ok; // Flag indicating the completion of receive DMA. + __IO BOOL tx_dma_ok; // Flag indicating the completion of transmit DMA. + + i2cs_dma_callback *dma_rx_cb; // Callback function called when receive DMA is completed. + i2cs_dma_callback *dma_tx_cb; // Callback function called when transmit DMA is completed. + + i2c_interface_t interface; // Structure containing the function pointers for the I2C interface. +}; + +/** + * @brief Creates an I2C slave instance with GPIO pins for clock and data. + * @param gpios The GPIO pins used for the I2C communication. + * @param delay_ticks The number of NOP instructions to delay the I2C communication. + * @return A pointer to the created I2C slave instance. + */ +extern i2c_t *i2c_create(i2c_gpio_group_t gpios, uint16_t delay_ticks); + +/** + * @brief Creates an I2C slave instance with DMA support. + * @param i2c Pointer to the I2C peripheral. + * @param dma Pointer to the DMA peripheral. + * @param rxsize Size of the receive buffer. + * @param dma_rx_channel DMA channel used for receiving data. + * @param dma_rx_cb Callback function called when receive DMA is completed. + * @param txsize Size of the transmit buffer. + * @param dma_tx_channel DMA channel used for transmitting data. + * @param dma_tx_cb Callback function called when transmit DMA is completed. + * @return A pointer to the created I2C slave instance. + */ +extern i2c_t *i2c_create_dma(I2C_TypeDef *i2c, DMA_TypeDef *dma, uint16_t rxsize, uint32_t dma_rx_channel, + i2cs_dma_callback *dma_rx_cb, uint16_t txsize, uint32_t dma_tx_channel, i2cs_dma_callback *dma_tx_cb); + +/** + * @brief Sets the write and read addresses for the I2C slave instance with DMA support. + * @param handle Pointer to the I2C slave instance. + * @param w_address 7-bit write address. + * @param r_address 7-bit read address. + */ +extern void i2c_dma_set_address(i2c_t *handle, uint8_t w_address, uint8_t r_address); + +/** + * @brief Frees the resources used by the I2C slave instance. + * @param handle Pointer to the I2C slave instance. + */ +extern void i2c_free(i2c_t *handle); + +/** + * @brief Callback function called when an I2C event occurs. + * @param handle Pointer to the I2C slave instance. + */ +extern void i2c_ev_callback(i2c_t *handle); + +/** + * @brief Callback function called when an I2C DMA event occurs. + * @param handle Pointer to the I2C slave instance. + */ +extern void i2c_dma_callback(i2c_t *handle); + +#endif // __I2CS_H__ diff --git a/User/system/bsp/iwdgs.c b/User/system/bsp/iwdgs.c new file mode 100644 index 0000000..8b4228b --- /dev/null +++ b/User/system/bsp/iwdgs.c @@ -0,0 +1,39 @@ +#include "iwdgs.h" + +/** + * @brief 检查判断CPU复位是否是看门狗复位 + * @return {BOOL} + * @note + */ +BOOL check_watchdog_reset(void) +{ + if (LL_RCC_IsActiveFlag_IWDGRST() == SET) // cpu is reset due to iwdg + { + LL_RCC_ClearResetFlags(); // clear flag + return TRUE; + } + else + { + return FALSE; + } +} + +/** + * @brief 调试模式冻结看门狗 + * @return {*} + * @note + */ +void debug_freeze_watchdog(void) +{ + LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP); +} + +/** + * @brief 调试模式恢复看门狗 + * @return {*} + * @note + */ +void debug_unfreeze_watchdog(void) +{ + LL_DBGMCU_APB1_GRP1_UnFreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP); +} diff --git a/User/system/bsp/iwdgs.h b/User/system/bsp/iwdgs.h new file mode 100644 index 0000000..9c91099 --- /dev/null +++ b/User/system/bsp/iwdgs.h @@ -0,0 +1,45 @@ +/** + * @file iwdgs.h + * @brief This file contains the declaration of the Independent Watchdog (IWDG) module. + * + * The Independent Watchdog (IWDG) is a hardware module in STM32 microcontrollers that provides a mechanism for system reset in case of software failures or malfunctions. This file declares the functions and constants related to the IWDG module. + * + * @author xxx + * @date 2023-12-27 14:44:03 + * @version 1.0 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __IWDGS_H__ +#define __IWDGS_H__ + +#include "main.h" +#include "lib.h" +/** + * @brief Reloads the watchdog counter. + * + * This macro is used to reload the watchdog counter, preventing the system from resetting. + */ +#define WATCHDOG_RESET() LL_IWDG_ReloadCounter(IWDG) + +/** + * @brief Checks if the system has been reset by the watchdog. + * + * @return BOOL Returns TRUE if the system has been reset by the watchdog, FALSE otherwise. + */ +extern BOOL check_watchdog_reset(void); + +/** + * @brief Freezes the watchdog timer for debugging purposes. + * + * This function freezes the watchdog timer, allowing for debugging without triggering a watchdog reset. + */ +extern void debug_freeze_watchdog(void); + +/** + * @brief Unfreezes the watchdog timer after debugging. + * + * This function unfreezes the watchdog timer, allowing it to resume normal operation after debugging. + */ +extern void debug_unfreeze_watchdog(void); + +#endif diff --git a/User/system/bsp/pwms.c b/User/system/bsp/pwms.c new file mode 100644 index 0000000..e69de29 diff --git a/User/system/bsp/pwms.h b/User/system/bsp/pwms.h new file mode 100644 index 0000000..94b5160 --- /dev/null +++ b/User/system/bsp/pwms.h @@ -0,0 +1,54 @@ +/** + * @file pwms.h + * @brief Header file for PWMs module. + * + * This file contains the declarations and documentation for the PWMs module. + * + * @author xxx + * @date 2023-12-27 14:44:03 + * @version 1.0 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __PWMS_H__ +#define __PWMS_H__ +#include "lib.h" +/** + * @brief Starts the PWM for a specific channel + * @param TIMx: TIM instance + * @param CHx: Channel to be started + * @retval None + */ +#define PWM_START(TIMx, CHx) \ + do \ + { \ + LL_TIM_EnableCounter(TIMx); \ + LL_TIM_CC_EnableChannel(TIMx, CHx); \ + } while (__LINE__ == -1) + +/** + * @brief Stops the PWM for a specific channel + * @param TIMx: TIM instance + * @param CHx: Channel to be stopped + * @retval None + */ +#define PWM_STOP(TIMx, CHx) \ + do \ + { \ + LL_TIM_DisableCounter(TIMx); \ + LL_TIM_CC_DisableChannel(TIMx, CHx); \ + } while (__LINE__ == -1) + +/** + * @brief Sets the duty cycle for a specific channel + * @param TIMx: TIM instance + * @param CHx: Channel to be set + * @param DUTY: Duty cycle value (0-100) + * @retval None + */ +#define PWM_SET_DUTY(TIMx, CHx, DUTY) \ + do \ + { \ + LL_TIM_OC_SetCompareCH##CHx(TIMx, DUTY); \ + } while (__LINE__ == -1) + +#endif // __PWMS_H__ diff --git a/User/system/bsp/readme.md b/User/system/bsp/readme.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/User/system/bsp/readme.md @@ -0,0 +1 @@ + diff --git a/User/system/bsp/spis.c b/User/system/bsp/spis.c new file mode 100644 index 0000000..92db8b6 --- /dev/null +++ b/User/system/bsp/spis.c @@ -0,0 +1,491 @@ +#include "spis.h" +static inline void spi_delay(spi_t *handle); // 延时函数 + +static inline void spi_rdy_high(spi_t *handle); // RDY高电平 +static inline void spi_rdy_low(spi_t *handle); // RDY低电平 +static inline void spi_cs_high(spi_t *handle); // CS高电平 +static inline void spi_cs_low(spi_t *handle); // CS低电平 +static inline void spi_mosi_high(spi_t *handle); // MOSI高电平 +static inline void spi_mosi_low(spi_t *handle); // MOSI低电平 +static inline void spi_sck_high(spi_t *handle); // SCK高电平 +static inline void spi_sck_low(spi_t *handle); // SCK低电平 +static inline uint8_t spi_miso_read(spi_t *handle); // 读取MISO电平 + +static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data); // 读写一个字节 + +static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi); // 硬件SPI +static void _dma_enable(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb, + uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); // DMA SPI +static void _spi_dma_callback(spi_t *handle); // DMA发送完成回调 +static void _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length); // DMA发送数据 +static uint8_t _read_drdy(spi_t *handle); // 读取DRDY电平 +static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 写多个寄存器 +static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // 读多个寄存器 +static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data); // 写单个寄存器 +static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg); // 读单个寄存器 +static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd); // 写命令 +static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len); // 写数据 + +/** + * @brief 创建一个SPI总线设备 + * @param {spi_type_e} spi_type SPI总线的类型 + * @param {spi_gpio_group_t} gpios SPI总线的GPIO配置 + * @param {uint16_t} delay_ticks SPI总线的延时参数 + * @return {*} 创建的SPI总线设备句柄 + * @note: 该函数用于创建一个SPI总线设备。它首先断言spi_type在有效的范围内,然后创建一个spi_t结构体,并将gpios和delay_ticks的内存地址复制到handle结构体中。接着,根据spi_type的值,设置不同的接口函数。最后,返回handle结构体。 + */ +spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks) +{ + DBG_ASSERT(spi_type < SPI_TYPE_MAX __DBG_LINE); + spi_t *handle = (spi_t *)osel_mem_alloc(sizeof(spi_t)); + osel_memcpy((uint8_t *)&handle->gpios, (uint8_t *)&gpios, sizeof(spi_gpio_group_t)); + handle->delay_ticks = delay_ticks; + handle->spi_type = spi_type; + handle->simualte_gpio = TRUE; + handle->interface.hardware_enable = _hardware_enable; + handle->interface.dma_enable = _dma_enable; + handle->interface.spi_dma_send = _spi_dma_send; + handle->interface.spi_dma_callback = _spi_dma_callback; + if (spi_type == SPI_TYPE_NORMAL) + { + handle->interface.u.normal.write_reg = _spi_write_reg; + handle->interface.u.normal.read_reg = _spi_read_reg; + handle->interface.u.normal.write_regs = _write_regs; + handle->interface.u.normal.read_regs = _read_regs; + handle->interface.u.normal.read_drdy = _read_drdy; + + handle->interface.u.normal.spi_send = spi_read_write_byte; + } + else if (spi_type == SPI_TYPE_LCD) + { + handle->interface.u.lcd.write_cmd = _spi_write_cmd; + handle->interface.u.lcd.write_data = _spi_write_data; + } + else + { + DBG_ASSERT(FALSE __DBG_LINE); + } + return handle; +} + +void spi_free(spi_t *handle) +{ + if (handle != NULL) + { + gpio_free(handle->gpios.cs); + gpio_free(handle->gpios.rdy); + gpio_free(handle->gpios.rst); + gpio_free(handle->gpios.mosi); + gpio_free(handle->gpios.miso); + gpio_free(handle->gpios.sck); + + osel_mem_free(handle); + } +} + +/** + * @brief 硬件SPI模式 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {SPI_TypeDef} *spi SPI总线的寄存器结构体指针 + * @return {*} 无 + * @note: 该函数用于设置SPI总线的硬件模式。它首先断言handle不为空,然后断言spix不为空。接着,将handle的simulate_gpio设置为FALSE,并将spix的地址赋值给handle->spix。最后,调用SPI_ENABLE函数启用SPI总线。 + */ +static void _hardware_enable(spi_t *handle, SPI_TypeDef *spi) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + DBG_ASSERT(spi != NULL __DBG_LINE); + handle->simualte_gpio = FALSE; + handle->spi = spi; + SPI_ENABLE(spi); +} + +static void _dma_enable(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb, + uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + DBG_ASSERT(dma != NULL __DBG_LINE); + DBG_ASSERT(handle->spi != NULL __DBG_LINE); + handle->dma = dma; + handle->dma_rx_channel = dma_rx_channel; + handle->dma_tx_channel = dma_tx_channel; + handle->rx_dma_ok = TRUE; + handle->tx_dma_ok = TRUE; + if (dma_rx_cb != NULL) + { + handle->dma_rx_cb = dma_rx_cb; + } + if (dma_tx_cb != NULL) + { + handle->dma_tx_cb = dma_tx_cb; + } + + LL_DMA_SetPeriphAddress(dma, dma_tx_channel, LL_SPI_DMA_GetRegAddr(handle->spi)); + LL_DMA_ClearFlag_GI1(dma); + LL_DMA_ClearFlag_TC1(dma); + LL_DMA_EnableIT_TC(dma, dma_tx_channel); + LL_SPI_EnableDMAReq_TX(handle->spi); + LL_SPI_Enable(handle->spi); +} + +static void _spi_dma_callback(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + if (handle->dma_tx_cb != NULL) + { + handle->dma_tx_cb(handle); + } + + if (handle->dma_rx_cb != NULL) + { + handle->dma_rx_cb(handle); + } +} + +static void _spi_dma_send(spi_t *handle, uint8_t *data, uint16_t length) +{ + handle->tx_dma_ok = FALSE; + LL_DMA_DisableChannel(handle->dma, handle->dma_tx_channel); + + LL_DMA_SetMemoryAddress(handle->dma, handle->dma_tx_channel, (uint32_t)data); + LL_DMA_SetDataLength(handle->dma, handle->dma_tx_channel, length); + + LL_DMA_EnableChannel(handle->dma, handle->dma_tx_channel); + + uint16_t i = 0; + while (handle->tx_dma_ok == FALSE) + { + i++; + if (i > 20000) + { + __NOP(); + break; + } + } +} + +/** + * @brief 读取数据准备好信号 + * @param {spi_t} *handle SPI总线设备句柄 + * @return {uint8_t} 数据准备好信号的值 + * @note: 该函数用于读取SPI总线的数据准备好信号。它首先断言handle不为空,然后返回handle的gpios.rdy的读取结果。 + */ +static uint8_t _read_drdy(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + return handle->gpios.rdy->read(*handle->gpios.rdy); +} + +/** + * @brief 写入单个寄存器 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} reg 寄存器号 + * @param {uint8_t} data 寄存器值 + * @return {*} 操作结果 + * @note: 该函数用于写入SPI总线的单个寄存器。它首先断言handle不为空,然后断言data不为空。接着,将SPI总线的CS引脚设置为低电平,发送寄存器号和寄存器值,最后将SPI总线的CS引脚设置为高电平,返回操作结果。 + */ +static uint8_t _write_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len) +{ + uint8_t status = 0; + DBG_ASSERT(handle != NULL __DBG_LINE); + DBG_ASSERT(data != NULL __DBG_LINE); + DBG_ASSERT(len != 0 __DBG_LINE); + spi_cs_low(handle); + status = spi_read_write_byte(handle, reg); // 发送寄存器号 + while (len--) + { + spi_read_write_byte(handle, *data); // 写入寄存器的值 + data++; + } + spi_cs_high(handle); + + return status; +} + +/** + * @brief 读取多个寄存器 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} reg 寄存器号 + * @param {uint8_t} *data 寄存器值的指针 + * @param {uint8_t} len 寄存器值的个数 + * @return {uint8_t} 操作结果 + * @note: 该函数用于读取SPI总线的多个寄存器。它首先断言handle不为空,然后断言data不为空,接着断言len大于0。接着,将SPI总线的CS引脚设置为低电平,发送寄存器号,然后循环读取多个寄存器的值,最后将SPI总线的CS引脚设置为高电平,返回操作结果。 + */ +static uint8_t _read_regs(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len) +{ + uint8_t status = 0; + + DBG_ASSERT(handle != NULL __DBG_LINE); + DBG_ASSERT(data != NULL __DBG_LINE); + DBG_ASSERT(len != 0 __DBG_LINE); + + spi_cs_low(handle); + status = spi_read_write_byte(handle, reg); + for (uint8_t i = 0; i < len; i++) + { + data[i] = spi_read_write_byte(handle, 0xff); // 读出数据 + } + spi_cs_high(handle); + + return status; +} + +/** + * @brief 写入单个寄存器 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} reg 寄存器号 + * @param {uint8_t} data 寄存器值 + * @return {*} 操作结果 + * @note: 该函数用于写入SPI总线的单个寄存器。它首先断言handle不为空,然后将SPI总线的CS引脚设置为低电平,发送寄存器号和寄存器值,最后将SPI总线的CS引脚设置为高电平,返回操作结果。 + */ +static uint8_t _spi_write_reg(spi_t *handle, uint8_t reg, uint8_t data) +{ + uint8_t status = 0; + DBG_ASSERT(handle != NULL __DBG_LINE); + + spi_cs_low(handle); + status = spi_read_write_byte(handle, reg); // 发送寄存器号 + spi_read_write_byte(handle, data); // 写入寄存器的值 + + spi_cs_high(handle); + + return status; +} + +/** + * @brief 读取单个寄存器 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} reg 寄存器号 + * @return {*} 寄存器值 + * @note: 该函数用于读取SPI总线的单个寄存器。它首先断言handle不为空,然后将SPI总线的CS引脚设置为低电平,发送寄存器号,接着读取寄存器的值,最后将SPI总线的CS引脚设置为高电平,返回寄存器值。 + */ +static uint8_t _spi_read_reg(spi_t *handle, uint8_t reg) +{ + uint8_t reg_val = 0; + DBG_ASSERT(handle != NULL __DBG_LINE); + + spi_cs_low(handle); + spi_read_write_byte(handle, reg); // 发送寄存器号 + reg_val = spi_read_write_byte(handle, 0); + spi_cs_high(handle); + + return reg_val; +} + +/** + * @brief 写入命令 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} cmd 命令 + * @return {*} 操作结果 + * @note: 该函数用于写入SPI总线的命令。它首先断言handle不为空,然后将SPI总线的RDY引脚设置为低电平,发送命令,最后将SPI总线的CS引脚设置为高电平,返回操作结果。 + */ +static uint8_t _spi_write_cmd(spi_t *handle, uint8_t cmd) +{ + uint8_t status = 0; + + DBG_ASSERT(handle != NULL __DBG_LINE); + spi_rdy_low(handle); + spi_cs_low(handle); + status = spi_read_write_byte(handle, cmd); // 发送命令 + spi_cs_high(handle); + return status; +} + +/** + * @brief 写入数据 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} *data 要写入的数据的指针 + * @param {uint16_t} len 要写入的数据的长度 + * @return {*} 操作结果 + * @note: 该函数用于写入SPI总线的数据。它首先断言handle不为空,然后将SPI总线的RDY引脚设置为高电平,发送数据,最后将SPI总线的CS引脚设置为高电平,返回操作结果。 + */ +static uint8_t _spi_write_data(spi_t *handle, uint8_t *data, uint16_t len) +{ + uint8_t status = 0; + DBG_ASSERT(handle != NULL __DBG_LINE); + spi_rdy_high(handle); + spi_cs_low(handle); + for (uint16_t i = 0; i < len; i++) + { + status = spi_read_write_byte(handle, *data); + data++; + } + spi_cs_high(handle); + return status; +} + +/** + * @brief SPI延时函数 + * @param {spi_t} *handle SPI总线设备句柄 + * @return {*} 无 + * @note: 该函数用于SPI总线的延时。它首先断言handle不为空,然后根据handle的delay_ticks的值,循环执行NOP指令。 + */ +static inline void spi_delay(spi_t *handle) +{ + uint16_t count = 0; + DBG_ASSERT(handle != NULL __DBG_LINE); + count = handle->delay_ticks; + while (count--) + { + __NOP(); + } +} + +/** + * @brief 读写一个字节 + * @param {spi_t} *handle SPI总线设备句柄 + * @param {uint8_t} tx_data 要写入的数据 + * @return {*} 读取到的数据 + * @note: 该函数用于SPI总线的读写一个字节。它首先断言handle不为空,然后根据handle的simulate_gpio的值,选择模拟SPI或硬件SPI。最后,返回读取到的数据。 + */ +static uint8_t spi_read_write_byte(spi_t *handle, uint8_t tx_data) +{ + uint8_t bit_ctr; + uint8_t rdata = 0xff; + uint16_t i = 0; + DBG_ASSERT(handle != NULL __DBG_LINE); + if (handle->simualte_gpio == TRUE) + { + // 模拟SPI + for (bit_ctr = 0; bit_ctr < 8; bit_ctr++) + { + spi_sck_low(handle); + spi_delay(handle); + + if (tx_data & 0x80) + spi_mosi_high(handle); + else + spi_mosi_low(handle); + + spi_delay(handle); + spi_sck_high(handle); + spi_delay(handle); + tx_data = (tx_data << 1); + rdata = rdata << 1; + + if (NULL != handle->gpios.miso->port) + { + if (spi_miso_read(handle) == 1) + rdata += 0x01; + } + } + return (rdata); + } + else + { + // 硬件SPI + LL_SPI_TransmitData8(handle->spi, tx_data); + while (LL_SPI_IsActiveFlag_TXE(handle->spi) == 0) + { + i++; + if (i > 2000) + break; + } + i = 0; + while (LL_SPI_IsActiveFlag_RXNE(handle->spi) == 0) + { + i++; + if (i > 2000) + break; + } + return LL_SPI_ReceiveData8(handle->spi); + } +} + +/** + * @brief 用于将SPI(串行外围接口)设备的复位(RST)引脚设置为高 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_rdy_high(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.rdy->set(*handle->gpios.rdy); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的复位(RST)引脚设置为低 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_rdy_low(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.rdy->reset(*handle->gpios.rdy); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的芯片选择(CS)引脚设置为高 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_cs_high(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.cs->set(*handle->gpios.cs); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的芯片选择(CS)引脚设置为低 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_cs_low(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.cs->reset(*handle->gpios.cs); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的时钟(SCK)引脚设置为高 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_mosi_high(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.mosi->set(*handle->gpios.mosi); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的输出(MOSI)引脚设置为低 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_mosi_low(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.mosi->reset(*handle->gpios.mosi); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的时钟(SCK)引脚设置为高 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_sck_high(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.sck->set(*handle->gpios.sck); +} + +/** + * @brief 用于将SPI(串行外围接口)设备的时钟(SCK)引脚设置为低 + * @param {spi_id_e} id + * @return {*} + */ +static inline void spi_sck_low(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + handle->gpios.sck->reset(*handle->gpios.sck); +} + +/** + * @brief 用于读取SPI(串行外围接口)设备的输入(MISO)引脚的电平 + * @param {spi_id_e} id + * @return {*} + */ +static inline uint8_t spi_miso_read(spi_t *handle) +{ + DBG_ASSERT(handle != NULL __DBG_LINE); + return handle->gpios.miso->read(*handle->gpios.miso); +} diff --git a/User/system/bsp/spis.h b/User/system/bsp/spis.h new file mode 100644 index 0000000..1f9136c --- /dev/null +++ b/User/system/bsp/spis.h @@ -0,0 +1,133 @@ +/** + * @file spis.h + * @brief SPI驱动, 用于SPI设备的读写操作 + * + * This file contains the SPI driver used for reading and writing operations on SPI devices. + * + * @date 2023-08-01 + * @version 1.0 + * + * @note This file is part of the STM32 controller-v2 project. + * + */ + +#ifndef __SPIS_H__ +#define __SPIS_H__ + +#include "lib.h" +#include "gpios.h" + +#define SPI_ENABLE(SPIX) LL_SPI_Enable(SPIX) + +typedef struct SPIS spi_t; +typedef void spis_dma_callback(spi_t *handle); + +/** + * @brief SPI type enumeration + */ +typedef enum +{ + SPI_TYPE_NORMAL = 0, // SPI1:NORMAL + SPI_TYPE_LCD, // SPI2:LCD + SPI_TYPE_MAX, +} spi_type_e; + +/** + * @brief SPI GPIO group structure + */ +typedef struct +{ + gpio_t *mosi; // MOSI + gpio_t *miso; // MISO + gpio_t *sck; // SCK + gpio_t *cs; // CS + gpio_t *rst; // RST + gpio_t *rdy; // DRDY +} spi_gpio_group_t; + +/** + * @brief SPI normal interface structure + */ +typedef struct +{ + uint8_t (*write_reg)(spi_t *handle, uint8_t reg, uint8_t data); // Write a single register via SPI + uint8_t (*read_reg)(spi_t *handle, uint8_t reg); // Read the value of a single register via SPI + uint8_t (*read_drdy)(spi_t *handle); // Get the value of the SPI DRDY pin + uint8_t (*write_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // Write multiple registers via SPI + uint8_t (*read_regs)(spi_t *handle, uint8_t reg, uint8_t *data, uint8_t len); // Read multiple registers via SPI + uint8_t (*spi_send)(spi_t *handle, uint8_t data); // Send data via SPI +} spi_normal_interface_t; + +/** + * @brief SPI LCD interface structure + */ +typedef struct +{ + uint8_t (*write_cmd)(spi_t *handle, uint8_t cmd); // Write a command via SPI + uint8_t (*write_data)(spi_t *handle, uint8_t *data, uint16_t len); // Write data via SPI +} spi_lcd_interface_t; + +/** + * @brief SPI interface structure + */ +typedef struct +{ + union + { + spi_normal_interface_t normal; + spi_lcd_interface_t lcd; + } u; + void (*hardware_enable)(spi_t *handle, SPI_TypeDef *spi); // Enable hardware SPI + void (*dma_enable)(spi_t *handle, DMA_TypeDef *dma, uint32_t dma_rx_channel, spis_dma_callback *dma_rx_cb, + uint32_t dma_tx_channel, spis_dma_callback *dma_tx_cb); // Enable DMA SPI + void (*spi_dma_callback)(spi_t *spi); // DMA send completion callback + void (*spi_dma_send)(spi_t *handle, uint8_t *data, uint16_t length); // DMA send +} spi_interface_t; + +/** + * @brief SPI structure + */ +typedef struct SPIS spi_t; + +/** + * @brief SPI DMA callback function + */ +typedef void spis_dma_callback(spi_t *handle); + +struct SPIS +{ + spi_type_e spi_type; // SPI type + uint16_t delay_ticks; // Delay in NOP ticks + spi_gpio_group_t gpios; // SPI GPIOs + spi_interface_t interface; // SPI interface + SPI_TypeDef *spi; // SPI peripheral + BOOL simualte_gpio; // Simulate GPIO + + // DMA + DMA_TypeDef *dma; // External setting + uint32_t dma_rx_channel; // External setting + uint32_t dma_tx_channel; // External setting + __IO BOOL rx_dma_ok; + __IO BOOL tx_dma_ok; + spis_dma_callback *dma_rx_cb; // DMA receive callback function + spis_dma_callback *dma_tx_cb; // DMA send callback function +}; + +/** + * @brief Create a new SPI instance + * + * @param spi_type The type of SPI + * @param gpios The SPI GPIO group + * @param delay_ticks The delay in NOP ticks + * @return spi_t* The created SPI instance + */ +extern spi_t *spi_create(spi_type_e spi_type, spi_gpio_group_t gpios, uint16_t delay_ticks); + +/** + * @brief Free the SPI instance + * + * @param spi The SPI instance to free + */ +extern void spi_free(spi_t *spi); + +#endif // __SPIS_H__ diff --git a/User/system/bsp/tims.c b/User/system/bsp/tims.c new file mode 100644 index 0000000..03d544d --- /dev/null +++ b/User/system/bsp/tims.c @@ -0,0 +1 @@ +#include "tims.h" diff --git a/User/system/bsp/tims.h b/User/system/bsp/tims.h new file mode 100644 index 0000000..50ce15f --- /dev/null +++ b/User/system/bsp/tims.h @@ -0,0 +1,102 @@ +/** + * @file tims.h + * @brief Header file for TIMS module. + * + * This file contains the declarations and definitions for the TIMS module. + * TIMS stands for Timer System and provides functionality related to timers. + * + * @author xxx + * @date 2024-01-16 22:23:43 + * @copyright Copyright (c) 2024 by xxx, All Rights Reserved. + */ +#ifndef __TIMS_H__ +#define __TIMS_H__ + +/** +Timer overflow time calculation formula +Tout = ((ARR + 1)*(PSC + 1)) / Tclk +Given Tclk as 84MHz, we need Tout to be 200ms or 200000us. Let's assume PSC is 839, substituting it into the formula gives ARR = 19999. +With these calculated values, both ARR and PSC are within the range of 0 to 65535, so we can use this parameter set. + */ + +/** + * @brief Enables the specified TIMx. + * @param TIMx TIM instance. + */ +#define ENABLE_TIM(TIMx) \ + do \ + { \ + LL_TIM_EnableCounter(TIMx); \ + LL_TIM_EnableIT_UPDATE(TIMx); \ + } while (__LINE__ == -1); + +/** + * @brief Checks if the specified TIMx is enabled. + * @param TIMx TIM instance. + * @retval The new state of TIMx (1 or 0). + */ +#define IS_ENABLE_TIM(TIMx) LL_TIM_IsEnabledIT_UPDATE(TIMx) + +/** + * @brief Disables the specified TIMx. + * @param TIMx TIM instance. + */ +#define DISABLE_TIM(TIMx) \ + do \ + { \ + LL_TIM_DisableCounter(TIMx); \ + LL_TIM_DisableIT_UPDATE(TIMx); \ + } while (__LINE__ == -1); + +/** + * @brief Checks if the specified TIMx interrupt flag is set. + * @param TIMx TIM instance. + * @retval The new state of the specified TIMx interrupt flag (1 or 0). + */ +#define IS_TIM_IT_FLAG(TIMx) (LL_TIM_IsActiveFlag_UPDATE(TIMx) == 1) + +/** + * @brief TIM interrupt handler. + * @param TIMx TIM instance. + */ +#define TIM_IRQ_HANDLER(TIMx) \ + do \ + { \ + if (LL_TIM_IsActiveFlag_CC1(TIMx) == SET) \ + { \ + if (LL_TIM_IsEnabledIT_CC1(TIMx) == SET) \ + { \ + LL_TIM_ClearFlag_CC1(TIMx); \ + } \ + } \ + if (LL_TIM_IsActiveFlag_CC2(TIMx) == SET) \ + { \ + if (LL_TIM_IsEnabledIT_CC2(TIMx) == SET) \ + { \ + LL_TIM_ClearFlag_CC2(TIMx); \ + } \ + } \ + if (LL_TIM_IsActiveFlag_CC3(TIMx) == SET) \ + { \ + if (LL_TIM_IsEnabledIT_CC3(TIMx) == SET) \ + { \ + LL_TIM_ClearFlag_CC3(TIMx); \ + } \ + } \ + if (LL_TIM_IsActiveFlag_CC4(TIMx) == SET) \ + { \ + if (LL_TIM_IsEnabledIT_CC4(TIMx) == SET) \ + { \ + LL_TIM_ClearFlag_CC4(TIMx); \ + } \ + } \ + if (LL_TIM_IsActiveFlag_UPDATE(TIMx) == SET) \ + { \ + if (LL_TIM_IsEnabledIT_UPDATE(TIMx) == SET) \ + { \ + LL_TIM_ClearFlag_UPDATE(TIMx); \ + } \ + } \ + } while (__LINE__ == -1) + +#endif // __TIMS_H__ diff --git a/User/system/bsp/uarts.c b/User/system/bsp/uarts.c new file mode 100644 index 0000000..6e82c7b --- /dev/null +++ b/User/system/bsp/uarts.c @@ -0,0 +1,380 @@ +/* + * @Author: + * @Date: 2023-07-31 11:47:35 + * @LastEditors: xxx + * @LastEditTime: 2023-08-25 15:30:33 + * @Description: LL库的串口驱动 + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ +#include "uarts.h" + +/** + * @brief 清除DMA传输完成标志 + * @param {DMA_HandleTypeDef} *DMAX DMA总线句柄 + * @param {uint32_t} CHx DMA通道号 + * @return {*} 操作结果 + * @note: 该宏用于清除DMA总线的传输完成标志。它首先检查DMA总线的传输完成标志是否已置位,如果已置位,则清除该标志。 + */ +#define DMA_ClEAR_FLAG_TC(DMAX, CHx) \ + do \ + { \ + if (LL_DMA_IsActiveFlag_TC##CHx(DMAX)) \ + { \ + LL_DMA_ClearFlag_TC##CHx(DMAX); \ + } \ + } while (__LINE__ == -1) + +/** + * @brief 清除DMA传输错误标志 + * @param {DMA_HandleTypeDef} *DMAX DMA总线句柄 + * @param {uint32_t} CHx DMA通道号 + * @return {*} 操作结果 + * @note: 该宏用于清除DMA总线的传输错误标志。它首先检查DMA总线的传输错误标志是否已置位,如果已置位,则清除该标志。 + */ +#define DMA_ClEAR_FLAG_TE(DMAX, CHx) \ + do \ + { \ + if (LL_DMA_IsActiveFlag_TE##CHx(DMAX)) \ + { \ + LL_DMA_ClearFlag_TE##CHx(DMAX); \ + } \ + } while (__LINE__ == -1) + +/** + * @file uarts.c + * @brief This file contains the implementation of DMA_CLEAR_FLAG_TC_CHANNEL macro. + */ + +/** + * @brief Clear the Transfer Complete (TC) flag of a specific DMA channel. + * + * @param dma The DMA peripheral. + * @param channel The DMA channel number. + */ +#define DMA_CLEAR_FLAG_TC_CHANNEL(dma, channel) \ + switch (channel) \ + { \ + case LL_DMA_CHANNEL_1: \ + DMA_ClEAR_FLAG_TC(dma, 1); \ + break; \ + case LL_DMA_CHANNEL_2: \ + DMA_ClEAR_FLAG_TC(dma, 2); \ + break; \ + case LL_DMA_CHANNEL_3: \ + DMA_ClEAR_FLAG_TC(dma, 3); \ + break; \ + case LL_DMA_CHANNEL_4: \ + DMA_ClEAR_FLAG_TC(dma, 4); \ + break; \ + case LL_DMA_CHANNEL_5: \ + DMA_ClEAR_FLAG_TC(dma, 5); \ + break; \ + case LL_DMA_CHANNEL_6: \ + DMA_ClEAR_FLAG_TC(dma, 6); \ + break; \ + case LL_DMA_CHANNEL_7: \ + DMA_ClEAR_FLAG_TC(dma, 7); \ + break; \ + default: \ + break; \ + } + +/** + * @brief Clear the Transfer Error (TE) flag for the specified DMA channel. + * + * @param dma The DMA peripheral. + * @param channel The DMA channel number. + */ +#define DMA_CLEAR_FLAG_TE_CHANNEL(dma, channel) \ + switch (channel) \ + { \ + case 1: \ + DMA_ClEAR_FLAG_TE(dma, 1); \ + break; \ + case 2: \ + DMA_ClEAR_FLAG_TE(dma, 2); \ + break; \ + case 3: \ + DMA_ClEAR_FLAG_TE(dma, 3); \ + break; \ + case 4: \ + DMA_ClEAR_FLAG_TE(dma, 4); \ + break; \ + case 5: \ + DMA_ClEAR_FLAG_TE(dma, 5); \ + break; \ + case 6: \ + DMA_ClEAR_FLAG_TE(dma, 6); \ + break; \ + case 7: \ + DMA_ClEAR_FLAG_TE(dma, 7); \ + break; \ + default: \ + break; \ + } + +/** + * @brief 创建一个UART设备 + * @param {USART_TypeDef} *huart USART总线设备句柄 + * @param {BOOL} rx_dma_en 接收DMA使能标志 + * @param {uint16_t} rxsize 接收缓冲区大小 + * @param {rx_interrupt_cb_t} rx_cb 接收中断回调函数 + * @param {BOOL} tx_dma_en 发送DMA使能标志 + * @param {uint16_t} txsize 发送缓冲区大小 + * @param {tx_complete_cb_t} tx_complete_cb 发送完成回调函数 + * @return {*} 创建的UART设备指针 + * @note: 该函数用于创建一个UART设备。它首先断言huart不为空,然后分配内存用于接收缓冲区和发送缓冲区,并设置相关标志。最后,返回创建的UART设备指针。 + */ +uart_t *uart_create(USART_TypeDef *huart, BOOL rx_dma_en, uint16_t rxsize, rx_interupt_cb_t rx_cb, + BOOL tx_dma_en, uint16_t txsize, tx_complete_cb_t tx_complete_cb) +{ + DBG_ASSERT(huart != NULL __DBG_LINE); + // 分配内存 + uart_t *uart = (uart_t *)osel_mem_alloc(sizeof(uart_t)); + DBG_ASSERT(uart != NULL __DBG_LINE); + + // 设置接收回调函数 + uart->rx_interupt_cb = rx_cb; + // 设置接收数据大小 + uart->rxsize = rxsize; + + // 设置发送完成回调函数 + uart->tx_complete_cb = tx_complete_cb; + // 设置发送数据大小 + uart->txsize = txsize; + // 如果接收大小大于0,则分配内存 + if (rxsize > 0) + { + uart->rxbuf = (uint8_t *)osel_mem_alloc(rxsize); + DBG_ASSERT(uart->rxbuf != NULL __DBG_LINE); + } + + // 如果发送大小大于0,则分配内存 + if (txsize > 0) + { + uart->txbuf = (uint8_t *)osel_mem_alloc(txsize); + DBG_ASSERT(uart->txbuf != NULL __DBG_LINE); + } + // 设置接收DMA禁用 + uart->rx_dma_en = rx_dma_en; + // 设置发送DMA禁用 + uart->tx_dma_en = tx_dma_en; + + // 设置huart + uart->huart = huart; + // 返回uart + return uart; +} + +/** + * @brief 使能UART接收 + * @param {uart_t} *uart UART设备句柄 + * @return {*} 操作结果 + * @note: 该函数用于使能UART设备的接收功能。它首先检查UART设备的接收DMA使能标志,然后禁用接收中断,配置RX DMA并启用RX DMA通道。最后,检查UART设备的发送DMA使能标志,配置TX DMA并启用TX DMA通道。 + */ +void uart_recv_en(uart_t *uart) +{ + if (FALSE == uart->rx_dma_en) + { + LL_USART_EnableIT_RXNE(uart->huart); // 使用接收中断处理 + } + else + { + LL_USART_ClearFlag_IDLE(uart->huart); + // LL_USART_EnableIT_RXNE(uart->huart); // 加上这个,否则第一条数据会接受不到 + + // 配置RX DMA + LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel); + LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel); + + // 配置RX DMA + LL_DMA_SetPeriphAddress(uart->dma, uart->dma_rx_channel, LL_USART_DMA_GetRegAddr(uart->huart, LL_USART_DMA_REG_DATA_RECEIVE)); + LL_DMA_SetMemoryAddress(uart->dma, uart->dma_rx_channel, (uint32_t)uart->rxbuf); + LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize); + LL_DMA_EnableIT_TC(uart->dma, uart->dma_rx_channel); + LL_DMA_EnableChannel(uart->dma, uart->dma_rx_channel); + LL_USART_EnableDMAReq_RX(uart->huart); + LL_USART_EnableIT_IDLE(uart->huart); + + // 配置TX DMA + LL_DMA_SetPeriphAddress(uart->dma, uart->dma_tx_channel, LL_USART_DMA_GetRegAddr(uart->huart, LL_USART_DMA_REG_DATA_TRANSMIT)); + // 配置内存地址 + LL_DMA_SetMemoryAddress(uart->dma, uart->dma_tx_channel, (uint32_t)uart->txbuf); + LL_DMA_EnableIT_TC(uart->dma, uart->dma_tx_channel); + LL_USART_EnableDMAReq_TX(uart->huart); + + uart->tx_dma_ok = TRUE; + } +} + +/** + * @brief 释放UART设备资源 + * @param {uart_t} *uart UART设备句柄 + * @return {*} 操作结果 + * @note: 该函数用于释放UART设备的接收缓冲区、发送缓冲区和UART设备本身。 + */ +void uart_free(uart_t *uart) +{ + if (uart != NULL) + { + if (uart->rxbuf != NULL) + { + osel_mem_free(uart->rxbuf); + } + if (uart->txbuf != NULL) + { + osel_mem_free(uart->txbuf); + } + osel_mem_free(uart); + } +} + +/** + * @brief 发送数据 + * @param {uart_t} *uart UART设备句柄 + * @param {uint8_t} *data 要发送的数据 + * @param {uint16_t} len 要发送的数据长度 + * @return {*} 操作结果 + * @note: 该函数用于发送数据。首先检查UART设备的发送DMA使能标志,然后禁用发送中断,配置TX DMA并启用TX DMA通道。最后,发送数据直到发送缓冲区满或发送中断发生。 + */ +void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len) +{ + DBG_ASSERT(uart != NULL __DBG_LINE); + DBG_ASSERT(data != NULL __DBG_LINE); + DBG_ASSERT(len > 0 __DBG_LINE); + uint8_t count = 0; + if (TRUE == uart->tx_dma_en) + { + if (uart->tx_dma_ok == FALSE) + { + return; + } + uart->tx_dma_ok = FALSE; + osel_memcpy(uart->txbuf, data, len); // 拷贝数据到发送缓冲区 + LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel); + // 配置数据长度 + LL_DMA_SetDataLength(uart->dma, uart->dma_tx_channel, len); + // 使能DMA STREAM 也就是发送数据 + LL_DMA_EnableChannel(uart->dma, uart->dma_tx_channel); + } + else + { + count = 0; + for (uint16_t i = 0; i < len; i++) + { + count = 0; + while (!LL_USART_IsActiveFlag_TXE(uart->huart)) + { + if (count++ >= 0xFE) + { + return; + } + } + LL_USART_TransmitData8(uart->huart, data[i]); + } + count = 0; + while (!LL_USART_IsActiveFlag_TC(uart->huart)) + { + if (count++ >= 0xFE) + { + return; + } + } + } +} + +/** + * @brief 接收中断回调函数 + * @param {uart_t} *uart UART设备句柄 + * @return {*} 操作结果 + * @note: 该函数用于处理接收中断。首先检查接收DMA使能标志,然后禁用接收中断,配置RX DMA并启用RX DMA通道。当接收到数据时,将数据复制到接收缓冲区,并调用接收中断回调函数。当接收缓冲区满时,关闭RX DMA通道并重置接收索引。 + */ +void uart_reception_callback(uart_t *uart) +{ + DBG_ASSERT(uart != NULL __DBG_LINE); + if (LL_USART_IsEnabledIT_RXNE(uart->huart) && LL_USART_IsActiveFlag_RXNE(uart->huart)) + { + uart->rxbuf[uart->rx_index++] = LL_USART_ReceiveData8(uart->huart); + if (uart->rx_dma_en == FALSE) // 中断方式:一个字节一个字节的接收 + { + if (uart->rx_interupt_cb != NULL) + { + uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index); + } + uart->rx_index = 0; + } + } + else if (LL_USART_IsEnabledIT_IDLE(uart->huart) && LL_USART_IsActiveFlag_IDLE(uart->huart)) + { + if (uart->rx_dma_en == TRUE) + { + LL_DMA_DisableChannel(uart->dma, uart->dma_rx_channel); + uart->rx_index = uart->rxsize - LL_DMA_GetDataLength(uart->dma, uart->dma_rx_channel); + if (uart->rx_interupt_cb != NULL && (uart->rx_index > 0 && uart->rx_index <= uart->rxsize)) + { + uart->rx_interupt_cb(uart->uart_index, uart->rxbuf, uart->rx_index); + osel_memset(uart->rxbuf, 0, uart->rxsize); + } + LL_DMA_SetDataLength(uart->dma, uart->dma_rx_channel, uart->rxsize); // 这个不能少 先关闭DMA才能重新设置长度 + LL_DMA_EnableChannel(uart->dma, uart->dma_rx_channel); + } + + uart->rx_index = 0; + LL_USART_ClearFlag_IDLE(uart->huart); + } + + if (LL_USART_IsEnabledIT_TC(uart->huart) && LL_USART_IsActiveFlag_TC(uart->huart)) + { + if (uart->tx_complete_cb != NULL) + { + uart->tx_complete_cb(); + } + LL_USART_ClearFlag_TC(uart->huart); + } + + if (LL_USART_IsEnabledIT_PE(uart->huart) && LL_USART_IsActiveFlag_PE(uart->huart)) + { + LL_USART_ClearFlag_PE(uart->huart); + } + + if (LL_USART_IsActiveFlag_FE(uart->huart) && LL_USART_IsActiveFlag_FE(uart->huart)) + { + LL_USART_ClearFlag_FE(uart->huart); + } + + if (LL_USART_IsActiveFlag_NE(uart->huart) && LL_USART_IsActiveFlag_NE(uart->huart)) + { + LL_USART_ClearFlag_NE(uart->huart); + } + + if (LL_USART_IsActiveFlag_ORE(uart->huart) && LL_USART_IsActiveFlag_ORE(uart->huart)) + { + LL_USART_ClearFlag_ORE(uart->huart); + } +} + +/** + * @brief 用于处理串口DMA接收中断的回调函数 + * @param {uart_t} *uart - 串口对象 + * @return {*} 无 + * @note: + */ +void uart_dma_reception_callback(uart_t *uart) +{ + // 检查输入参数是否为空 + DBG_ASSERT(uart != NULL __DBG_LINE); + + // 禁用串口DMA的发送通道 + LL_DMA_DisableChannel(uart->dma, uart->dma_tx_channel); + + // 清除发送中断标志位 + DMA_CLEAR_FLAG_TC_CHANNEL(uart->dma, uart->dma_tx_channel); + + // 使能发送中断,用于关闭发送使能引脚 + LL_USART_EnableIT_TC(uart->huart); // 使能发送中断,用于关闭发送使能引脚 + uart->tx_dma_ok = TRUE; + + // 清除传输错误标志 + DMA_CLEAR_FLAG_TE_CHANNEL(uart->dma, uart->dma_tx_channel); +} diff --git a/User/system/bsp/uarts.h b/User/system/bsp/uarts.h new file mode 100644 index 0000000..45fc902 --- /dev/null +++ b/User/system/bsp/uarts.h @@ -0,0 +1,132 @@ +/** + * @file uarts.h + * @brief Header file for UARTs module. + * + * This file contains the definitions and function prototypes for UARTs module. + * The UARTs module provides functions for creating and managing UART instances, + * enabling reception, sending data, and handling interrupts. + */ + +#ifndef __UARTS_H__ +#define __UARTS_H__ + +#include "lib.h" +#include "main.h" + +/** + * @brief Callback function type for UART receive interrupt. + * + * This function type is used to define the callback function for UART receive interrupt. + * The callback function is called when data is received on the UART. + * + * @param uart_index The index of the UART. + * @param data The received data. + * @param len The length of the received data. + */ +typedef void (*rx_interupt_cb_t)(uint8_t uart_index, uint8_t *data, uint16_t len); + +/** + * @brief Callback function type for UART transmit complete. + * + * This function type is used to define the callback function for UART transmit complete. + * The callback function is called when the UART transmission is complete. + */ +typedef void (*tx_complete_cb_t)(void); + +/** + * @brief Enumeration for UART status. + */ +typedef enum +{ + UART_OK = 0x00u, /**< The action was successful. */ + UART_ERROR = 0xFFu /**< Generic error. */ +} uart_status_e; + +/** + * @brief Structure representing a UART instance. + */ +typedef struct +{ + uint8_t uart_index; /**< The index of the UART. */ + USART_TypeDef *huart; /**< The UART peripheral. */ + DMA_TypeDef *dma; /**< The DMA peripheral. */ + uint32_t dma_rx_channel; /**< The DMA receive channel. */ + uint32_t dma_tx_channel; /**< The DMA transmit channel. */ + uint16_t rx_index; /**< The receive data index. */ + BOOL rx_dma_en; /**< Flag indicating if DMA reception is enabled. */ + uint8_t *rxbuf; /**< The receive buffer. */ + uint16_t rxsize; /**< The size of the receive buffer. */ + uint16_t tx_index; /**< The transmit data index. */ + BOOL tx_dma_en; /**< Flag indicating if DMA transmission is enabled. */ + uint8_t *txbuf; /**< The transmit buffer. */ + uint16_t txsize; /**< The size of the transmit buffer. */ + __IO BOOL tx_dma_ok; /**< Flag indicating if DMA transmission is complete. */ + rx_interupt_cb_t rx_interupt_cb; /**< The receive interrupt callback function. */ + tx_complete_cb_t tx_complete_cb; /**< The transmit complete callback function. */ +} uart_t; + +/** + * @brief Creates a UART instance. + * + * This function creates a UART instance with the specified parameters. + * + * @param huart The UART peripheral. + * @param rx_dma_en Flag indicating if DMA reception is enabled. + * @param rxsize The size of the receive buffer. + * @param rx_cb The receive interrupt callback function. + * @param tx_dma_en Flag indicating if DMA transmission is enabled. + * @param txsize The size of the transmit buffer. + * @param tx_complete_cb The transmit complete callback function. + * @return The created UART instance. + */ +extern uart_t *uart_create(USART_TypeDef *huart, BOOL rx_dma_en, uint16_t rxsize, rx_interupt_cb_t rx_cb, + BOOL tx_dma_en, uint16_t txsize, tx_complete_cb_t tx_complete_cb); + +/** + * @brief Frees the resources of a UART instance. + * + * This function frees the resources allocated for a UART instance. + * + * @param uart The UART instance to free. + */ +extern void uart_free(uart_t *uart); + +/** + * @brief Enables UART reception. + * + * This function enables reception on the specified UART instance. + * + * @param uart The UART instance. + */ +extern void uart_recv_en(uart_t *uart); + +/** + * @brief Sends data over UART. + * + * This function sends the specified data over the specified UART instance. + * + * @param uart The UART instance. + * @param data The data to send. + * @param len The length of the data. + */ +extern void uart_send_data(uart_t *uart, uint8_t *data, uint16_t len); + +/** + * @brief UART receive interrupt callback. + * + * This function is the interrupt callback for UART receive interrupt. + * + * @param uart The UART instance. + */ +extern void uart_reception_callback(uart_t *uart); + +/** + * @brief DMA receive interrupt callback. + * + * This function is the interrupt callback for DMA receive interrupt. + * + * @param uart The UART instance. + */ +extern void uart_dma_reception_callback(uart_t *uart); + +#endif // __UARTS_H__ diff --git a/User/system/inc/btn.h b/User/system/inc/btn.h new file mode 100644 index 0000000..9f6991b --- /dev/null +++ b/User/system/inc/btn.h @@ -0,0 +1,163 @@ +/*** + * @Author: + * @Date: 2023-07-04 08:26:12 + * @LastEditors: xxx + * @LastEditTime: 2023-08-09 22:49:14 + * @Description: btn是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式 + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +/** +使用方法: +1.先申请一个按键结构 + +struct Button button1; +2.初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平 + +button_init(&button1, read_button_pin, 0, 0); +3.注册按键事件 + +button_attach(&button1, SINGLE_CLICK, Callback_SINGLE_CLICK_Handler); +button_attach(&button1, DOUBLE_CLICK, Callback_DOUBLE_Click_Handler); +... +4.启动按键 + +button_start(&button1); +5.设置一个5ms间隔的定时器循环调用后台处理函数 + +while(1) { + ... + if(timer_ticks == 5) { + timer_ticks = 0; + + button_ticks(); + } +} +*/ +#ifndef _BTN_H_ +#define _BTN_H_ + +#ifdef STM32 +#include "lib.h" +#else +#include "stdint.h" +#include "string.h" +#endif + +// 根据您的需求修改常量。 +#define TICKS_INTERVAL 10 // 按钮扫描间隔,单位ms +#define DEBOUNCE_TICKS 3 // 按键去抖动时间,单位ms +#define SHORT_TICKS (100 / TICKS_INTERVAL) // 短按时间阈值,单位ms +#define LONG_TICKS (500 / TICKS_INTERVAL) // 长按时间阈值,单位ms + +typedef void (*BtnCallback)(void *); + +typedef enum +{ + ACTIVE_LEVEL_LOW = 0, // 低电平有效 + ACTIVE_LEVEL_HIGH, // 高电平有效 +} active_level_e; + +/*** + * @brief + 事件 说明 + PRESS_DOWN 按键按下,每次按下都触发 + PRESS_UP 按键弹起,每次松开都触发 + PRESS_REPEAT 重复按下触发,变量repeat计数连击次数 + SINGLE_CLICK 单击按键事件 + DOUBLE_CLICK 双击按键事件 + LONG_PRESS_START 达到长按时间阈值时触发一次 + LONG_PRESS_HOLD 长按期间一直触发 + */ +typedef enum +{ + PRESS_DOWN = 0, // 按下 + PRESS_UP, // 弹起 + PRESS_REPEAT, // 重复按下 + SINGLE_CLICK, // 单击 + DOUBLE_CLICK, // 双击 + LONG_PRESS_START, // 长按开始 + LONG_PRESS_HOLD, // 长按保持 + number_of_event, // 事件数量 + NONE_PRESS // 无按键 +} PressEvent; + +/*** + * @brief 按钮设备结构体 + */ +typedef struct Button +{ + uint16_t ticks; // 计时器 + uint8_t repeat : 4; // 重复计数 + uint8_t event : 4; // 事件类型 + uint8_t state : 3; // 状态 + uint8_t debounce_cnt : 3; // 去抖计数 + uint8_t active_level : 1; // 激活电平 + uint8_t button_level : 1; // 按钮电平 + uint8_t button_id; // 按钮ID + uint8_t (*hal_button_Level)(uint8_t button_id_); // 获取按钮引脚电平函数 + BtnCallback cb[number_of_event]; // 回调函数数组 + struct Button *next; // 下一个按钮句柄 +} Button; + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** + * @brief 初始化按钮设备 + * @param handle: 按钮句柄结构体 + * @param pin_level: 获取按钮引脚电平函数 + * @param active_level: 按钮激活电平 + * @param button_id: 按钮ID + * @retval 0: 成功 + * @retval -1: 失败 + */ + void button_init(struct Button *handle, uint8_t (*pin_level)(uint8_t), active_level_e active_level, uint8_t button_id); + + /** + * @brief 附加按钮事件处理函数 + * @param handle: 按钮句柄结构体 + * @param event: 按钮事件 + * @param cb: 回调函数 + * @retval 0: 成功 + * @retval -1: 失败 + */ + void button_attach(struct Button *handle, PressEvent event, BtnCallback cb); + + /** + * @brief 获取按钮事件 + * @param handle: 按钮句柄结构体 + * @retval 按钮事件 + */ + PressEvent get_button_event(struct Button *handle); + + /** + * @brief 启动按钮工作 + * @param handle: 按钮句柄结构体 + * @retval 0: 成功 + * @retval -1: 已存在 + */ + int button_start(struct Button *handle); + + /** + * @brief 停止按钮工作 + * @param handle: 按钮句柄结构体 + * @retval None + */ + void button_stop(struct Button *handle); + + /** + * @brief 后台计时,定时器重复调用间隔为5ms + * @param None + * @retval None + */ + void button_ticks(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/User/system/inc/delay.h b/User/system/inc/delay.h new file mode 100644 index 0000000..ac129de --- /dev/null +++ b/User/system/inc/delay.h @@ -0,0 +1,21 @@ +/*** + * @Author: + * @Date: 2023-04-11 18:31:07 + * @LastEditors: xxx + * @LastEditTime: 2023-04-11 18:31:20 + * @Description: + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef __DELAY_H +#define __DELAY_H + +#include "sys.h" + +void delay_init(uint16_t sysclk); /* 初始化延迟函数 */ +void delay_ms(uint16_t nms); /* 延时nms */ +void delay_us(uint32_t nus); /* 延时nus */ +void delay_tick(uint32_t ticks); /* 延时ticks */ + +#endif diff --git a/User/system/inc/sys.h b/User/system/inc/sys.h new file mode 100644 index 0000000..a121c2a --- /dev/null +++ b/User/system/inc/sys.h @@ -0,0 +1,38 @@ +/*** + * @Author: + * @Date: 2023-04-11 18:46:58 + * @LastEditors: xxx + * @LastEditTime: 2023-04-11 22:16:47 + * @Description: + * @email: + * @Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#ifndef _SYS_H +#define _SYS_H + +#include "main.h" +#include "lib.h" + +#define LOCK() __disable_irq() ///< 系统关全局中断 +#define UNLOCK() __enable_irq() ///< 系统开全局中断 + +void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset); /* 设置中断偏移量 */ +void sys_standby(void); /* 进入待机模式 */ +void sys_soft_reset(void); /* 系统软复位 */ +void LL_IncTick(void); /* 系统滴答时钟 */ +void sys_millis_reset(void); /* 系统计时器重新开始 */ +uint32_t sys_get_tick(void); /* 获取系统滴答时钟 */ +uint32_t sys_millis(void); /* 获取系统时间 */ +uint32_t sys_to_seconds(uint32_t start_time); /* 将系统时间转换为秒 */ + +// 以下为汇编函数 +void sys_wfi_set(void); /* 执行WFI指令 */ +void sys_intx_disable(void); /* 关闭所有中断 */ +void sys_intx_enable(void); /* 开启所有中断 */ +void sys_msr_msp(uint32_t addr); /* 设置栈顶地址 */ + +void scheduler_time_start(void); +uint32_t scheduler_time_stop(void); +uint32_t scheduler_time_occupancy_get(uint32_t run_time); +#endif diff --git a/User/system/readme.txt b/User/system/readme.txt new file mode 100644 index 0000000..f9c613d --- /dev/null +++ b/User/system/readme.txt @@ -0,0 +1,4 @@ +1,delay文件夹:存放延时相关的驱动代码。 +2,sys文件夹:存放系统相关驱动代码。 +3,uart文件夹:存放串口相关代码。 + \ No newline at end of file diff --git a/User/system/src/btn.c b/User/system/src/btn.c new file mode 100644 index 0000000..688f928 --- /dev/null +++ b/User/system/src/btn.c @@ -0,0 +1,247 @@ +/* + * @Author: + * @Date: 2023-07-04 08:25:56 + * @LastEditors: xxx + * @LastEditTime: 2023-08-25 11:13:52 + * @Description:一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰 + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "../inc/btn.h" + +#define EVENT_CB(ev) \ + if (handle->cb[ev]) \ + handle->cb[ev]((Button *)handle) + +// button handle list head. +static struct Button *head_handle = NULL; + +/** + * @brief 初始化按钮结构体句柄。 + * @param handle: 按钮句柄结构体。 + * @param pin_level: 读取按钮连接的HAL GPIOLevel。 + * @param active_level: 按下按钮的GPIOLevel。 + * @param button_id: 按钮ID。 + * @retval 无 + */ +void button_init(struct Button *handle, uint8_t (*pin_level)(uint8_t), active_level_e active_level, uint8_t button_id) +{ +#ifdef STM32 + osel_memset((uint8_t *)handle, 0, sizeof(struct Button)); +#else + memset(handle, 0, sizeof(struct Button)); +#endif + + handle->event = (uint8_t)NONE_PRESS; + handle->hal_button_Level = pin_level; + handle->button_level = handle->hal_button_Level(button_id); + handle->active_level = (uint8_t)active_level; + handle->button_id = button_id; +} + +/** + * @brief 为按钮添加事件回调函数。 + * @param handle: 按钮句柄结构体。 + * @param event: 触发事件类型。 + * @param cb: 回调函数。 + * @retval 无 + */ +void button_attach(struct Button *handle, PressEvent event, BtnCallback cb) +{ + handle->cb[event] = cb; +} + +/** + * @brief 查询按钮发生的事件。 + * @param handle: 按钮句柄结构体。 + * @retval 按钮事件。 + */ +PressEvent get_button_event(struct Button *handle) +{ + return (PressEvent)(handle->event); +} + +/** + * @brief 按钮驱动核心函数,驱动状态机。 + * @param handle: 按钮句柄结构体。 + * @retval 无 + */ +void button_handler(struct Button *handle) +{ + uint8_t read_gpio_level = handle->hal_button_Level(handle->button_id); + + // ticks counter working.. + if ((handle->state) > 0) + handle->ticks++; + + /*------------button debounce handle---------------*/ + if (read_gpio_level != handle->button_level) + { // not equal to prev one + // continue read 3 times same new level change + if (++(handle->debounce_cnt) >= DEBOUNCE_TICKS) + { + handle->button_level = read_gpio_level; + handle->debounce_cnt = 0; + } + } + else + { // leved not change ,counter reset. + handle->debounce_cnt = 0; + } + + /*-----------------State machine-------------------*/ + switch (handle->state) + { + case 0: + if (handle->button_level == handle->active_level) + { // start press down + handle->event = (uint8_t)PRESS_DOWN; + EVENT_CB(PRESS_DOWN); + handle->ticks = 0; + handle->repeat = 1; + handle->state = 1; + } + else + { + handle->event = (uint8_t)NONE_PRESS; + } + break; + + case 1: + if (handle->button_level != handle->active_level) + { // released press up + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + handle->ticks = 0; + handle->state = 2; + } + else if (handle->ticks > LONG_TICKS) + { + handle->event = (uint8_t)LONG_PRESS_START; + EVENT_CB(LONG_PRESS_START); + handle->state = 5; + } + break; + + case 2: + if (handle->button_level == handle->active_level) + { // press down again + handle->event = (uint8_t)PRESS_DOWN; + EVENT_CB(PRESS_DOWN); + handle->repeat++; + EVENT_CB(PRESS_REPEAT); // repeat hit + handle->ticks = 0; + handle->state = 3; + } + else if (handle->ticks > SHORT_TICKS) + { // released timeout + if (handle->repeat == 1) + { + handle->event = (uint8_t)SINGLE_CLICK; + EVENT_CB(SINGLE_CLICK); + } + else if (handle->repeat == 2) + { + handle->event = (uint8_t)DOUBLE_CLICK; + EVENT_CB(DOUBLE_CLICK); // repeat hit + } + handle->state = 0; + } + break; + + case 3: + if (handle->button_level != handle->active_level) + { // released press up + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + if (handle->ticks < SHORT_TICKS) + { + handle->ticks = 0; + handle->state = 2; // repeat press + } + else + { + handle->state = 0; + } + } + else if (handle->ticks > SHORT_TICKS) + { // long press up + handle->state = 0; + } + break; + + case 5: + if (handle->button_level == handle->active_level) + { + // continue hold trigger + handle->event = (uint8_t)LONG_PRESS_HOLD; + EVENT_CB(LONG_PRESS_HOLD); + } + else + { // releasd + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + handle->state = 0; // reset + } + break; + default: + handle->state = 0; // reset + break; + } +} + +/** + * @brief 启动按钮工作,将句柄添加到工作队列中。 + * @param handle: 目标句柄结构体。 + * @retval 0: 成功。-1: 已存在。 + */ +int button_start(struct Button *handle) +{ + struct Button *target = head_handle; + while (target) + { + if (target == handle) + return -1; // already exist. + target = target->next; + } + handle->next = head_handle; + head_handle = handle; + return 0; +} + +/** + * @brief 停止按钮工作,从工作队列中移除句柄。 + * @param handle: 目标句柄结构体。 + * @retval None + */ +void button_stop(struct Button *handle) +{ + struct Button **curr; + for (curr = &head_handle; *curr;) + { + struct Button *entry = *curr; + if (entry == handle) + { + *curr = entry->next; + // free(entry); + return; + } + else + curr = &entry->next; + } +} + +/** + * @brief 后台计时,定时器重复调用间隔为5ms。 + * @param None. + * @retval None + */ +void button_ticks() +{ + struct Button *target; + for (target = head_handle; target; target = target->next) + { + button_handler(target); + } +} diff --git a/User/system/src/delay.c b/User/system/src/delay.c new file mode 100644 index 0000000..1c42a61 --- /dev/null +++ b/User/system/src/delay.c @@ -0,0 +1,116 @@ +/* + * @Author: + * @Date: 2023-04-11 18:31:07 + * @LastEditors: xxx + * @LastEditTime: 2023-08-25 11:27:12 + * @Description: + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "delay.h" +// static uint16_t g_fac_ms = 0; // ms延时倍乘数,在os下,代表每个节拍的ms数 +static uint32_t g_fac_us = 0; /* us延时倍乘数 */ + +void SysTick_Init(void) +{ + NVIC_SetPriority(SysTick_IRQn, 3); + LL_SYSTICK_EnableIT(); +} +/** + * @brief 初始化延迟函数 + * @param sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck) + * @retval 无 + */ +void delay_init(uint16_t sysclk) +{ +#if SYS_SUPPORT_OS /* 如果需要支持OS */ + uint32_t reload; +#endif + // SysTick_Init(); + // LL_SetSystemCoreClock(LL_SYSTICK_CLKSOURCE_HCLK); /* SYSTICK使用内核时钟源,同CPU同频率 */ + g_fac_us = sysclk; /* 不论是否使用OS,g_fac_us都需要使用 */ + // Remove the redundant assignment statement +#if SYS_SUPPORT_OS /* 如果需要支持OS. */ + reload = sysclk; /* 每秒钟的计数次数 单位为M */ + reload *= 1000000 / configTICK_RATE_HZ; /* 根据delay_ostickspersec设定溢出时间,reload为24位 + * 寄存器,最大值:16777216,在168M下,约合0.099s左右 + */ + g_fac_ms = 1000 / configTICK_RATE_HZ; // 代表OS可以延时的最少单位 + SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; /* 开启SYSTICK中断 */ + SysTick->LOAD = reload; /* 每1/delay_ostickspersec秒中断一次 */ + SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开启SYSTICK */ +#endif +} + +/** + * @brief 延时nus + * @param nus: 要延时的us数. + * @note 注意: nus的值,不要大于34952us(最大值即2^24 / g_fac_us @g_fac_us = 168) + * @retval 无 + */ +void delay_us(uint32_t nus) +{ + uint32_t ticks; + uint32_t told, tnow, tcnt = 0; + uint32_t reload = SysTick->LOAD; /* LOAD的值 */ + ticks = nus * g_fac_us; /* 需要的节拍数 */ + told = SysTick->VAL; /* 刚进入时的计数器值 */ + while (1) + { + tnow = SysTick->VAL; + if (tnow != told) + { + if (tnow < told) + { + tcnt += told - tnow; /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */ + } + else + { + tcnt += reload - tnow + told; + } + told = tnow; + if (tcnt >= ticks) + { + __NOP(); + break; /* 时间超过/等于要延迟的时间,则退出 */ + } + } + } +} + +/** + * @brief 延时nms + * @param nms: 要延时的ms数 (0< nms <= 65535) + * @retval 无 + */ +void delay_ms(uint16_t nms) +{ + uint32_t repeat = nms / 30; /* 这里用30,是考虑到可能有超频应用 */ + uint32_t remain = nms % 30; + + while (repeat) + { + delay_us(30 * 1000); /* 利用delay_us 实现 1000ms 延时 */ + repeat--; + } + + if (remain) + { + delay_us(remain * 1000); /* 利用delay_us, 把尾数延时(remain ms)给做了 */ + } +} + +/** + * @brief 延时函数,用于模拟硬件延时。 + * @param {uint32_t} ticks + * @return {*} + * @note: 请注意,这个函数仅用于模拟硬件延时,实际应用中可能需要使用其他延时函数,如HAL_Delay或rt_delay。 + */ +void delay_tick(uint32_t ticks) +{ + while (ticks--) + { + __NOP(); + } +} diff --git a/User/system/src/sys.c b/User/system/src/sys.c new file mode 100644 index 0000000..669c0df --- /dev/null +++ b/User/system/src/sys.c @@ -0,0 +1,175 @@ +/* + * @Author: + * @Date: 2023-04-11 18:46:58 + * @LastEditors: xxx + * @LastEditTime: 2023-08-25 11:31:06 + * @Description: + * email: + * Copyright (c) 2023 by xxx, All Rights Reserved. + */ + +#include "sys.h" +__IO uint32_t uwTick; +__IO uint32_t scheduler_start_time; // 调度器开始时间 +__IO uint32_t scheduler_end_time; // 调度器结束时间 +__IO uint32_t scheduler_occupancy_time = 0; // 调度器占用时间 +/** + * @brief 设置中断向量表偏移地址 + * @param baseaddr : 基址 + * @param offset : 偏移量 + * @retval 无 + */ +void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset) +{ + /* 设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留 */ + SCB->VTOR = baseaddr | (offset & (uint32_t)0xFFFFFE00); +} + +/** + * @brief 执行: WFI指令(执行完该指令进入低功耗状态, 等待中断唤醒) + * @param 无 + * @retval 无 + */ +void sys_wfi_set(void) +{ + __ASM __IO("wfi"); +} + +/** + * @brief 关闭所有中断(但是不包括fault和NMI中断) + * @param 无 + * @retval 无 + */ +void sys_intx_disable(void) +{ + __ASM __IO("cpsid i"); +} + +/** + * @brief 开启所有中断 + * @param 无 + * @retval 无 + */ +void sys_intx_enable(void) +{ + __ASM __IO("cpsie i"); +} + +/** + * @brief 设置栈顶地址 + * @note 左侧若有红X, 属于MDK误报, 实际是没问题的 + * @param addr: 栈顶地址 + * @retval 无 + */ +void sys_msr_msp(uint32_t addr) +{ + __set_MSP(addr); /* 设置栈顶地址 */ +} + +/** + * @brief 进入待机模式 + * @param 无 + * @retval 无 + */ +void sys_standby(void) +{ + // LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); /* 使能电源时钟 */ + // SET_BIT(PWR->CR, PWR_CR_PDDS); /* 进入待机模式 */ +} + +/** + * @brief 系统软复位 + * @param 无 + * @retval 无 + */ +void sys_soft_reset(void) +{ + NVIC_SystemReset(); +} + +/** + * @brief 10ms滴答定时器,需要单独放到定时器中断中执行 + * @param 无 + * @retval 提供给sys_millis()函数使用,之前放在SysTick_Handler中执行影响精度 + */ +__weak void LL_IncTick(void) +{ + uwTick += 1; +} + +/** + * @brief 获取系统当前滴答计数 + * @param 无 + * @retval 当前滴答计数 + */ +uint32_t sys_get_tick(void) +{ + return uwTick; +} + +/** + * @brief 获取系统当前毫秒级时间戳。 + * @return {uint32_t} 当前毫秒级时间戳 + * @note: 请注意,这个函数仅用于模拟硬件延时,实际应用中可能需要使用其他时钟源,如RTC或外部时钟。 + */ +uint32_t sys_millis(void) +{ + return uwTick * 10; +} + +/** + * @brief 系统计时器重新开始 + * @return {*} + * @note + */ +void sys_millis_reset(void) +{ + uwTick = 0; +} + +/** + * @brief 将系统时间戳转换为秒级时间戳。 + * @param {uint32_t} start_time 开始时间戳 + * @return {uint32_t} 秒级时间戳 + * @note: 请注意,这个函数仅用于模拟硬件延时,实际应用中可能需要使用其他时钟源,如RTC或外部时钟。 + */ +uint32_t sys_to_seconds(uint32_t start_time) +{ + return (sys_millis() - start_time) / 1000; +} + +/** + * @brief 记录调度器开始时间 + * @return {*} + * @note + */ +void scheduler_time_start(void) +{ + scheduler_start_time = sys_millis(); +} + +/** + * @brief 返回调度器运行时间 + * @return {*} + * @note + */ +uint32_t scheduler_time_stop(void) +{ + uint32_t scheduler_end_time = sys_millis() - scheduler_start_time; + scheduler_occupancy_time += scheduler_end_time; + return scheduler_end_time; +} + +/** + * @brief 计算任务占用时间百分比 + * @param {uint32_t} run_time 运行时间 + * @return {*} 任务占用时间百分比,单位为% + * @note + */ +uint32_t scheduler_time_occupancy_get(uint32_t run_time) +{ + float32 percent = 0.0f; + percent = (float32)(scheduler_occupancy_time) / (float32)run_time; + scheduler_occupancy_time = 0; + return (uint32_t)(percent * 100); +} diff --git a/bash.exe.stackdump b/bash.exe.stackdump new file mode 100644 index 0000000..43fb1c2 --- /dev/null +++ b/bash.exe.stackdump @@ -0,0 +1,16 @@ +Stack trace: +Frame Function Args +00800000010 0018006401E (001802839A0, 0018026EFD1, 00000000059, 000FFFFB720) +00800000010 0018004973A (00800000010, 00100000000, 00000000000, 00000000001) +00800000010 00180049772 (00000000000, 00000000000, 00000000059, 001803538B0) +00800000010 00180070FE9 (000FFFFCCE0, 000FFFFC7F0, 0000000000B, 00000000000) +00800000010 001800712A0 (00000000003, 000FFFFC910, 00180045BCF, 000FFFFC910) +00800000010 00180072AB9 (000FFFFC910, 00180271795, 001801004A7, 0000000000D) +00800000010 0018005B2A3 (000FFFFCA60, 00000000000, 00000000000, 008FFFFFFFF) +00800000010 0018005C655 (00000000002, 00800018300, 000FFFFCB90, 00100001000) +00800000010 0018005CB3F (000FFFFCCE0, 008000399C0, 000FFFFCC60, 000FFFFCC90) +000FFFFCBDC 0018005CF06 (00000000035, 000FFFFCCE0, 000FFFFCE00, 00000000000) +000FFFFCCE0 00180049EE8 (00000000000, 00000000000, 00000000000, 00000000000) +000FFFFFFF0 00180048846 (00000000000, 00000000000, 00000000000, 00000000000) +000FFFFFFF0 001800488F4 (00000000000, 00000000000, 00000000000, 00000000000) +End of stack trace diff --git a/controller-v2.ioc b/controller-v2.ioc new file mode 100644 index 0000000..c7cf81c --- /dev/null +++ b/controller-v2.ioc @@ -0,0 +1,738 @@ +#MicroXplorer Configuration settings - do not modify +ADC1.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_5 +ADC1.Channel-10\#ChannelRegularConversion=ADC_CHANNEL_VREFINT +ADC1.Channel-11\#ChannelRegularConversion=ADC_CHANNEL_TEMPSENSOR +ADC1.Channel-2\#ChannelRegularConversion=ADC_CHANNEL_6 +ADC1.Channel-3\#ChannelRegularConversion=ADC_CHANNEL_7 +ADC1.Channel-4\#ChannelRegularConversion=ADC_CHANNEL_8 +ADC1.Channel-5\#ChannelRegularConversion=ADC_CHANNEL_9 +ADC1.Channel-6\#ChannelRegularConversion=ADC_CHANNEL_11 +ADC1.Channel-7\#ChannelRegularConversion=ADC_CHANNEL_12 +ADC1.Channel-8\#ChannelRegularConversion=ADC_CHANNEL_13 +ADC1.Channel-9\#ChannelRegularConversion=ADC_CHANNEL_14 +ADC1.ClockPrescaler=ADC_CLOCK_ASYNC_DIV64 +ADC1.CommonPathInternal=ADC_CHANNEL_VREFINT|ADC_CHANNEL_TEMPSENSOR|null|null +ADC1.ContinuousConvMode=ENABLE +ADC1.DMAContinuousRequests=ENABLE +ADC1.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,OffsetNumber-1\#ChannelRegularConversion,NbrOfConversionFlag,Rank-2\#ChannelRegularConversion,Channel-2\#ChannelRegularConversion,SamplingTime-2\#ChannelRegularConversion,OffsetNumber-2\#ChannelRegularConversion,Rank-3\#ChannelRegularConversion,Channel-3\#ChannelRegularConversion,SamplingTime-3\#ChannelRegularConversion,OffsetNumber-3\#ChannelRegularConversion,NbrOfConversion,Rank-4\#ChannelRegularConversion,Channel-4\#ChannelRegularConversion,SamplingTime-4\#ChannelRegularConversion,OffsetNumber-4\#ChannelRegularConversion,ContinuousConvMode,DMAContinuousRequests,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,OffsetNumber-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,OffsetNumber-6\#ChannelRegularConversion,Rank-7\#ChannelRegularConversion,Channel-7\#ChannelRegularConversion,SamplingTime-7\#ChannelRegularConversion,OffsetNumber-7\#ChannelRegularConversion,Rank-8\#ChannelRegularConversion,Channel-8\#ChannelRegularConversion,SamplingTime-8\#ChannelRegularConversion,OffsetNumber-8\#ChannelRegularConversion,Rank-9\#ChannelRegularConversion,Channel-9\#ChannelRegularConversion,SamplingTime-9\#ChannelRegularConversion,OffsetNumber-9\#ChannelRegularConversion,Rank-10\#ChannelRegularConversion,Channel-10\#ChannelRegularConversion,SamplingTime-10\#ChannelRegularConversion,OffsetNumber-10\#ChannelRegularConversion,Rank-11\#ChannelRegularConversion,Channel-11\#ChannelRegularConversion,SamplingTime-11\#ChannelRegularConversion,OffsetNumber-11\#ChannelRegularConversion,ClockPrescaler,Overrun,master,CommonPathInternal +ADC1.NbrOfConversion=11 +ADC1.NbrOfConversionFlag=1 +ADC1.OffsetNumber-1\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-10\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-11\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-2\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-3\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-4\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-5\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-6\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-7\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-8\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.OffsetNumber-9\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC1.Overrun=ADC_OVR_DATA_PRESERVED +ADC1.Rank-1\#ChannelRegularConversion=1 +ADC1.Rank-10\#ChannelRegularConversion=10 +ADC1.Rank-11\#ChannelRegularConversion=11 +ADC1.Rank-2\#ChannelRegularConversion=2 +ADC1.Rank-3\#ChannelRegularConversion=3 +ADC1.Rank-4\#ChannelRegularConversion=4 +ADC1.Rank-5\#ChannelRegularConversion=5 +ADC1.Rank-6\#ChannelRegularConversion=6 +ADC1.Rank-7\#ChannelRegularConversion=7 +ADC1.Rank-8\#ChannelRegularConversion=8 +ADC1.Rank-9\#ChannelRegularConversion=9 +ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC1.SamplingTime-10\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC1.SamplingTime-11\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC1.SamplingTime-2\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5 +ADC1.SamplingTime-3\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5 +ADC1.SamplingTime-4\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5 +ADC1.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC1.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC1.SamplingTime-7\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC1.SamplingTime-8\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5 +ADC1.SamplingTime-9\#ChannelRegularConversion=ADC_SAMPLETIME_47CYCLES_5 +ADC1.master=1 +ADC2.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_5 +ADC2.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_6 +ADC2.ClockPrescaler=ADC_CLOCK_ASYNC_DIV64 +ADC2.CommonPathInternal=null|null|null|null +ADC2.ContinuousConvMode=ENABLE +ADC2.DMAContinuousRequests=ENABLE +ADC2.IPParameters=Rank-0\#ChannelRegularConversion,ClockPrescaler,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,ContinuousConvMode,DMAContinuousRequests,Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,OffsetNumber-1\#ChannelRegularConversion,NbrOfConversion,CommonPathInternal +ADC2.NbrOfConversion=2 +ADC2.NbrOfConversionFlag=1 +ADC2.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC2.OffsetNumber-1\#ChannelRegularConversion=ADC_OFFSET_NONE +ADC2.Rank-0\#ChannelRegularConversion=1 +ADC2.Rank-1\#ChannelRegularConversion=2 +ADC2.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +ADC2.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_640CYCLES_5 +CAD.formats=[] +CAD.pinconfig=Project naming +CAD.provider= +DAC1.DAC_Channel-DAC_OUT2=DAC_CHANNEL_2 +DAC1.DAC_OutputBuffer-DAC_OUT2=DAC_OUTPUTBUFFER_DISABLE +DAC1.IPParameters=DAC_Channel-DAC_OUT2,DAC_OutputBuffer-DAC_OUT2 +Dma.ADC1.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.ADC1.0.Instance=DMA1_Channel1 +Dma.ADC1.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.ADC1.0.MemInc=DMA_MINC_ENABLE +Dma.ADC1.0.Mode=DMA_CIRCULAR +Dma.ADC1.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.ADC1.0.PeriphInc=DMA_PINC_DISABLE +Dma.ADC1.0.Priority=DMA_PRIORITY_LOW +Dma.ADC1.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.ADC2.8.Direction=DMA_PERIPH_TO_MEMORY +Dma.ADC2.8.Instance=DMA1_Channel2 +Dma.ADC2.8.MemDataAlignment=DMA_MDATAALIGN_HALFWORD +Dma.ADC2.8.MemInc=DMA_MINC_ENABLE +Dma.ADC2.8.Mode=DMA_CIRCULAR +Dma.ADC2.8.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD +Dma.ADC2.8.PeriphInc=DMA_PINC_DISABLE +Dma.ADC2.8.Priority=DMA_PRIORITY_LOW +Dma.ADC2.8.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.I2C1_RX.6.Direction=DMA_PERIPH_TO_MEMORY +Dma.I2C1_RX.6.Instance=DMA1_Channel7 +Dma.I2C1_RX.6.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.I2C1_RX.6.MemInc=DMA_MINC_ENABLE +Dma.I2C1_RX.6.Mode=DMA_NORMAL +Dma.I2C1_RX.6.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.I2C1_RX.6.PeriphInc=DMA_PINC_DISABLE +Dma.I2C1_RX.6.Priority=DMA_PRIORITY_LOW +Dma.I2C1_RX.6.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.I2C1_TX.7.Direction=DMA_MEMORY_TO_PERIPH +Dma.I2C1_TX.7.Instance=DMA1_Channel6 +Dma.I2C1_TX.7.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.I2C1_TX.7.MemInc=DMA_MINC_ENABLE +Dma.I2C1_TX.7.Mode=DMA_NORMAL +Dma.I2C1_TX.7.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.I2C1_TX.7.PeriphInc=DMA_PINC_DISABLE +Dma.I2C1_TX.7.Priority=DMA_PRIORITY_LOW +Dma.I2C1_TX.7.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.Request0=ADC1 +Dma.Request1=UART5_RX +Dma.Request2=UART5_TX +Dma.Request3=SPI2_TX +Dma.Request4=USART1_RX +Dma.Request5=USART1_TX +Dma.Request6=I2C1_RX +Dma.Request7=I2C1_TX +Dma.Request8=ADC2 +Dma.RequestsNb=9 +Dma.SPI2_TX.3.Direction=DMA_MEMORY_TO_PERIPH +Dma.SPI2_TX.3.Instance=DMA1_Channel5 +Dma.SPI2_TX.3.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.SPI2_TX.3.MemInc=DMA_MINC_ENABLE +Dma.SPI2_TX.3.Mode=DMA_NORMAL +Dma.SPI2_TX.3.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.SPI2_TX.3.PeriphInc=DMA_PINC_DISABLE +Dma.SPI2_TX.3.Priority=DMA_PRIORITY_LOW +Dma.SPI2_TX.3.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.UART5_RX.1.Direction=DMA_PERIPH_TO_MEMORY +Dma.UART5_RX.1.Instance=DMA2_Channel2 +Dma.UART5_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.UART5_RX.1.MemInc=DMA_MINC_ENABLE +Dma.UART5_RX.1.Mode=DMA_NORMAL +Dma.UART5_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.UART5_RX.1.PeriphInc=DMA_PINC_DISABLE +Dma.UART5_RX.1.Priority=DMA_PRIORITY_LOW +Dma.UART5_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.UART5_TX.2.Direction=DMA_MEMORY_TO_PERIPH +Dma.UART5_TX.2.Instance=DMA2_Channel1 +Dma.UART5_TX.2.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.UART5_TX.2.MemInc=DMA_MINC_ENABLE +Dma.UART5_TX.2.Mode=DMA_NORMAL +Dma.UART5_TX.2.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.UART5_TX.2.PeriphInc=DMA_PINC_DISABLE +Dma.UART5_TX.2.Priority=DMA_PRIORITY_LOW +Dma.UART5_TX.2.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.USART1_RX.4.Direction=DMA_PERIPH_TO_MEMORY +Dma.USART1_RX.4.Instance=DMA2_Channel7 +Dma.USART1_RX.4.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART1_RX.4.MemInc=DMA_MINC_ENABLE +Dma.USART1_RX.4.Mode=DMA_NORMAL +Dma.USART1_RX.4.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART1_RX.4.PeriphInc=DMA_PINC_DISABLE +Dma.USART1_RX.4.Priority=DMA_PRIORITY_LOW +Dma.USART1_RX.4.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +Dma.USART1_TX.5.Direction=DMA_MEMORY_TO_PERIPH +Dma.USART1_TX.5.Instance=DMA2_Channel6 +Dma.USART1_TX.5.MemDataAlignment=DMA_MDATAALIGN_BYTE +Dma.USART1_TX.5.MemInc=DMA_MINC_ENABLE +Dma.USART1_TX.5.Mode=DMA_NORMAL +Dma.USART1_TX.5.PeriphDataAlignment=DMA_PDATAALIGN_BYTE +Dma.USART1_TX.5.PeriphInc=DMA_PINC_DISABLE +Dma.USART1_TX.5.Priority=DMA_PRIORITY_LOW +Dma.USART1_TX.5.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority +File.Version=6 +GPIO.groupedBy=Group By Peripherals +I2C1.I2C_Fall_Time=0 +I2C1.I2C_Rise_Time=0 +I2C1.I2C_Speed_Mode=I2C_Standard +I2C1.IPParameters=Speed,I2C_Speed_Mode,I2C_Rise_Time,I2C_Fall_Time +I2C1.Speed=100 +KeepUserPlacement=false +Mcu.CPN=STM32L476VGT6 +Mcu.Family=STM32L4 +Mcu.IP0=ADC1 +Mcu.IP1=ADC2 +Mcu.IP10=TIM2 +Mcu.IP11=TIM3 +Mcu.IP12=TIM6 +Mcu.IP13=TIM7 +Mcu.IP14=UART5 +Mcu.IP15=USART1 +Mcu.IP2=DAC1 +Mcu.IP3=DMA +Mcu.IP4=I2C1 +Mcu.IP5=NVIC +Mcu.IP6=RCC +Mcu.IP7=SPI1 +Mcu.IP8=SPI2 +Mcu.IP9=SYS +Mcu.IPNb=16 +Mcu.Name=STM32L476V(C-E-G)Tx +Mcu.Package=LQFP100 +Mcu.Pin0=PE5 +Mcu.Pin1=PH0-OSC_IN (PH0) +Mcu.Pin10=PA3 +Mcu.Pin11=PA4 +Mcu.Pin12=PA5 +Mcu.Pin13=PA6 +Mcu.Pin14=PA7 +Mcu.Pin15=PC4 +Mcu.Pin16=PC5 +Mcu.Pin17=PB0 +Mcu.Pin18=PB1 +Mcu.Pin19=PB2 +Mcu.Pin2=PH1-OSC_OUT (PH1) +Mcu.Pin20=PE7 +Mcu.Pin21=PE8 +Mcu.Pin22=PE9 +Mcu.Pin23=PE15 +Mcu.Pin24=PB10 +Mcu.Pin25=PB11 +Mcu.Pin26=PB12 +Mcu.Pin27=PB13 +Mcu.Pin28=PB15 +Mcu.Pin29=PD8 +Mcu.Pin3=PC0 +Mcu.Pin30=PD9 +Mcu.Pin31=PD10 +Mcu.Pin32=PD11 +Mcu.Pin33=PD12 +Mcu.Pin34=PD13 +Mcu.Pin35=PD14 +Mcu.Pin36=PD15 +Mcu.Pin37=PC6 +Mcu.Pin38=PC7 +Mcu.Pin39=PC8 +Mcu.Pin4=PC1 +Mcu.Pin40=PC9 +Mcu.Pin41=PA12 +Mcu.Pin42=PA13 (JTMS-SWDIO) +Mcu.Pin43=PA14 (JTCK-SWCLK) +Mcu.Pin44=PA15 (JTDI) +Mcu.Pin45=PC10 +Mcu.Pin46=PC12 +Mcu.Pin47=PD0 +Mcu.Pin48=PD2 +Mcu.Pin49=PD5 +Mcu.Pin5=PC2 +Mcu.Pin50=PD6 +Mcu.Pin51=PD7 +Mcu.Pin52=PB3 (JTDO-TRACESWO) +Mcu.Pin53=PB4 (NJTRST) +Mcu.Pin54=PB5 +Mcu.Pin55=PB6 +Mcu.Pin56=PB7 +Mcu.Pin57=PB8 +Mcu.Pin58=PB9 +Mcu.Pin59=PE0 +Mcu.Pin6=PC3 +Mcu.Pin60=PE1 +Mcu.Pin61=VP_ADC1_TempSens_Input +Mcu.Pin62=VP_ADC1_Vref_Input +Mcu.Pin63=VP_SYS_VS_Systick +Mcu.Pin64=VP_TIM2_VS_ClockSourceINT +Mcu.Pin65=VP_TIM3_VS_ClockSourceINT +Mcu.Pin66=VP_TIM6_VS_ClockSourceINT +Mcu.Pin67=VP_TIM7_VS_ClockSourceINT +Mcu.Pin68=VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0 +Mcu.Pin7=PA0 +Mcu.Pin8=PA1 +Mcu.Pin9=PA2 +Mcu.PinsNb=69 +Mcu.ThirdParty0=STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0 +Mcu.ThirdPartyNb=1 +Mcu.UserConstants= +Mcu.UserName=STM32L476VGTx +MxCube.Version=6.9.2 +MxDb.Version=DB.6.0.92 +NVIC.ADC1_2_IRQn=true\:14\:0\:true\:false\:true\:true\:true\:true +NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DMA1_Channel1_IRQn=true\:14\:0\:true\:false\:true\:false\:true\:true +NVIC.DMA1_Channel2_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA1_Channel5_IRQn=true\:14\:0\:true\:false\:true\:false\:true\:true +NVIC.DMA1_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA1_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA2_Channel1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA2_Channel2_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA2_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA2_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.ForceEnableDMAVector=true +NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.I2C1_EV_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true +NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4 +NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.SysTick_IRQn=true\:15\:0\:true\:false\:true\:false\:true\:false +NVIC.TIM6_DAC_IRQn=true\:6\:0\:true\:false\:true\:true\:true\:true +NVIC.TIM7_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true +NVIC.UART5_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:true +NVIC.USART1_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:true +NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +PA0.Signal=ADCx_IN5 +PA1.GPIOParameters=GPIO_Label +PA1.GPIO_Label=ADC_PSB_CHANNEL +PA1.Signal=ADCx_IN6 +PA12.GPIOParameters=GPIO_PuPd,GPIO_Label +PA12.GPIO_Label=HART_RTS +PA12.GPIO_PuPd=GPIO_PULLUP +PA12.Signal=GPIO_Output +PA13\ (JTMS-SWDIO).Mode=Serial_Wire +PA13\ (JTMS-SWDIO).Signal=SYS_JTMS-SWDIO +PA14\ (JTCK-SWCLK).Mode=Serial_Wire +PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK +PA15\ (JTDI).GPIOParameters=GPIO_PuPd,GPIO_Label +PA15\ (JTDI).GPIO_Label=BLE_RST +PA15\ (JTDI).GPIO_PuPd=GPIO_PULLUP +PA15\ (JTDI).Signal=GPIO_Output +PA2.GPIOParameters=GPIO_Label +PA2.GPIO_Label=ADC_BP_CHANNEL +PA2.Signal=ADCx_IN7 +PA3.GPIOParameters=GPIO_Label +PA3.GPIO_Label=ADC_IPSB_CHANNEL +PA3.Signal=ADCx_IN8 +PA4.GPIOParameters=GPIO_Label +PA4.GPIO_Label=ADC_NTC_CHANNEL +PA4.Signal=ADCx_IN9 +PA5.GPIOParameters=GPIO_Label +PA5.GPIO_Label=DAC_CONTROL +PA5.Signal=COMP_DAC12_group +PA6.GPIOParameters=GPIO_Label +PA6.GPIO_Label=ADC_VIP_CHANNEL +PA6.Signal=ADCx_IN11 +PA7.GPIOParameters=GPIO_Label +PA7.GPIO_Label=ADC_DCDC_CHANNEL +PA7.Signal=ADCx_IN12 +PB0.GPIOParameters=GPIO_PuPd,GPIO_Label +PB0.GPIO_Label=HART_PWR +PB0.GPIO_PuPd=GPIO_PULLUP +PB0.Signal=GPIO_Output +PB1.GPIOParameters=GPIO_PuPd,GPIO_Label +PB1.GPIO_Label=IP_PWR +PB1.GPIO_PuPd=GPIO_PULLUP +PB1.Signal=GPIO_Output +PB10.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP +PB10.GPIO_Label=LCD_PWR +PB10.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_PP +PB10.GPIO_PuPd=GPIO_NOPULL +PB10.Signal=GPIO_Output +PB11.GPIOParameters=GPIO_Label +PB11.GPIO_Label=PWM_CONTROL +PB11.Signal=S_TIM2_CH4 +PB12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label +PB12.GPIO_Label=LCD_CS +PB12.GPIO_PuPd=GPIO_NOPULL +PB12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH +PB12.Signal=GPIO_Output +PB13.GPIOParameters=GPIO_PuPd,GPIO_Label +PB13.GPIO_Label=LCD_SCK +PB13.GPIO_PuPd=GPIO_PULLUP +PB13.Mode=TX_Only_Simplex_Unidirect_Master +PB13.Signal=SPI2_SCK +PB15.GPIOParameters=GPIO_PuPd,GPIO_Label +PB15.GPIO_Label=LCD_MOSI +PB15.GPIO_PuPd=GPIO_PULLUP +PB15.Mode=TX_Only_Simplex_Unidirect_Master +PB15.Signal=SPI2_MOSI +PB2.GPIOParameters=GPIO_Label +PB2.GPIO_Label=IP_H_PWR +PB2.Signal=GPIO_Output +PB3\ (JTDO-TRACESWO).GPIOParameters=GPIO_Label +PB3\ (JTDO-TRACESWO).GPIO_Label=SPI_CLK +PB3\ (JTDO-TRACESWO).Mode=Full_Duplex_Master +PB3\ (JTDO-TRACESWO).Signal=SPI1_SCK +PB4\ (NJTRST).GPIOParameters=GPIO_Label +PB4\ (NJTRST).GPIO_Label=SPI_MISO +PB4\ (NJTRST).Mode=Full_Duplex_Master +PB4\ (NJTRST).Signal=SPI1_MISO +PB5.GPIOParameters=GPIO_Label +PB5.GPIO_Label=SPI_MOSI +PB5.Mode=Full_Duplex_Master +PB5.Signal=SPI1_MOSI +PB6.GPIOParameters=GPIO_Label +PB6.GPIO_Label=HART_TX +PB6.Mode=Asynchronous +PB6.Signal=USART1_TX +PB7.GPIOParameters=GPIO_Label +PB7.GPIO_Label=HART_RX +PB7.Mode=Asynchronous +PB7.Signal=USART1_RX +PB8.GPIOParameters=GPIO_Label +PB8.GPIO_Label=I2C1_SCL +PB8.Mode=I2C +PB8.Signal=I2C1_SCL +PB9.GPIOParameters=GPIO_Label +PB9.GPIO_Label=I2C1_SDA +PB9.Mode=I2C +PB9.Signal=I2C1_SDA +PC0.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP +PC0.GPIO_Label=RTC_SCL +PC0.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PC0.GPIO_PuPd=GPIO_NOPULL +PC0.Signal=GPIO_Output +PC1.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP +PC1.GPIO_Label=RTC_SDA +PC1.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PC1.GPIO_PuPd=GPIO_NOPULL +PC1.Signal=GPIO_Output +PC10.GPIOParameters=GPIO_PuPd,GPIO_Label +PC10.GPIO_Label=HART_RST +PC10.GPIO_PuPd=GPIO_PULLUP +PC10.Signal=GPIO_Output +PC12.GPIOParameters=GPIO_Label +PC12.GPIO_Label=BLE_TX +PC12.Mode=Asynchronous +PC12.Signal=UART5_TX +PC2.GPIOParameters=GPIO_Label +PC2.GPIO_Label=SWO1 +PC2.Signal=GPIO_Output +PC3.GPIOParameters=GPIO_Label +PC3.GPIO_Label=SWO2 +PC3.Signal=GPIO_Output +PC4.GPIOParameters=GPIO_Label +PC4.GPIO_Label=ADC_BPA_CHANNEL +PC4.Signal=ADCx_IN13 +PC5.GPIOParameters=GPIO_Label +PC5.GPIO_Label=ADC_BPB_CHANNEL +PC5.Signal=ADCx_IN14 +PC6.GPIOParameters=GPIO_PuPd,GPIO_Label +PC6.GPIO_Label=KEY4 +PC6.GPIO_PuPd=GPIO_NOPULL +PC6.Signal=GPIO_Input +PC7.GPIOParameters=GPIO_PuPd,GPIO_Label +PC7.GPIO_Label=KEY3 +PC7.GPIO_PuPd=GPIO_NOPULL +PC7.Signal=GPIO_Input +PC8.GPIOParameters=GPIO_PuPd,GPIO_Label +PC8.GPIO_Label=KEY2 +PC8.GPIO_PuPd=GPIO_NOPULL +PC8.Signal=GPIO_Input +PC9.GPIOParameters=GPIO_PuPd,GPIO_Label +PC9.GPIO_Label=KEY1 +PC9.GPIO_PuPd=GPIO_NOPULL +PC9.Signal=GPIO_Input +PCC.Checker=true +PCC.Line=STM32L4x6 +PCC.MCU=STM32L476V(C-E-G)Tx +PCC.PartNumber=STM32L476VGTx +PCC.Seq0=2 +PCC.Seq0.Step0.Average_Current=799.6 \u00B5A +PCC.Seq0.Step0.CPU_Frequency=4 MHz +PCC.Seq0.Step0.Category=In DS Table +PCC.Seq0.Step0.DMIPS=5.0 +PCC.Seq0.Step0.Duration=0.1 ms +PCC.Seq0.Step0.Frequency=4 MHz +PCC.Seq0.Step0.Memory=FLASH/ART/Cache +PCC.Seq0.Step0.Mode=RUN +PCC.Seq0.Step0.Oscillator=HSE +PCC.Seq0.Step0.Peripherals=ADC1\:fs_10_ksps AHB_APB1_Bridge AHB_APB2_Bridge DAC1\:OUT2-Buffer_OFF-Middle_code GPIOA GPIOB GPIOC GPIOD GPIOE GPIOH I2C1 SPI1 SPI2 TIM2 TIM3 TIM6 TIM7 UART5 USART1 +PCC.Seq0.Step0.TaMax=104.9 +PCC.Seq0.Step0.User's_Consumption=0 mA +PCC.Seq0.Step0.Vcore=Range2-Medium +PCC.Seq0.Step0.Vdd=3.0 +PCC.Seq0.Step0.Voltage_Source=Battery +PCC.Seq0.Step1.Average_Current=1.18 \u00B5A +PCC.Seq0.Step1.CPU_Frequency=0 Hz +PCC.Seq0.Step1.Category=In DS Table +PCC.Seq0.Step1.DMIPS=0.0 +PCC.Seq0.Step1.Duration=0.9 ms +PCC.Seq0.Step1.Frequency=0 Hz +PCC.Seq0.Step1.Memory=n/a +PCC.Seq0.Step1.Mode=STOP2 +PCC.Seq0.Step1.Oscillator=ALL CLOCKS OFF +PCC.Seq0.Step1.Peripherals= +PCC.Seq0.Step1.TaMax=105 +PCC.Seq0.Step1.User's_Consumption=0 mA +PCC.Seq0.Step1.Vcore=NoRange +PCC.Seq0.Step1.Vdd=3.0 +PCC.Seq0.Step1.Voltage_Source=Battery +PCC.Series=STM32L4 +PCC.Temperature=25 +PCC.Vdd=3.0 +PD0.GPIOParameters=GPIO_Label +PD0.GPIO_Label=HART_CD +PD0.Signal=GPIO_Input +PD10.GPIOParameters=PinState,GPIO_Label +PD10.GPIO_Label=LED2 +PD10.PinState=GPIO_PIN_SET +PD10.Signal=GPIO_Output +PD11.GPIOParameters=PinState,GPIO_Label +PD11.GPIO_Label=LED3 +PD11.PinState=GPIO_PIN_SET +PD11.Signal=GPIO_Output +PD12.GPIOParameters=PinState,GPIO_Label +PD12.GPIO_Label=LED4 +PD12.PinState=GPIO_PIN_SET +PD12.Signal=GPIO_Output +PD13.GPIOParameters=PinState,GPIO_Label +PD13.GPIO_Label=LED5 +PD13.PinState=GPIO_PIN_SET +PD13.Signal=GPIO_Output +PD14.GPIOParameters=GPIO_PuPd,GPIO_Label +PD14.GPIO_Label=KEY6 +PD14.GPIO_PuPd=GPIO_NOPULL +PD14.Signal=GPIO_Input +PD15.GPIOParameters=GPIO_PuPd,GPIO_Label +PD15.GPIO_Label=KEY5 +PD15.GPIO_PuPd=GPIO_NOPULL +PD15.Signal=GPIO_Input +PD2.GPIOParameters=GPIO_Label +PD2.GPIO_Label=BLE_RX +PD2.Mode=Asynchronous +PD2.Signal=UART5_RX +PD5.GPIOParameters=GPIO_PuPd,GPIO_Label +PD5.GPIO_Label=EE2_CS +PD5.GPIO_PuPd=GPIO_NOPULL +PD5.Signal=GPIO_Output +PD6.GPIOParameters=GPIO_PuPd,GPIO_Label +PD6.GPIO_Label=EE1_CS +PD6.GPIO_PuPd=GPIO_PULLUP +PD6.Signal=GPIO_Output +PD7.GPIOParameters=GPIO_Label +PD7.GPIO_Label=BLE_PWR +PD7.Signal=GPIO_Output +PD8.GPIOParameters=PinState,GPIO_PuPd,GPIO_Label +PD8.GPIO_Label=LCD_DISP +PD8.GPIO_PuPd=GPIO_NOPULL +PD8.PinState=GPIO_PIN_RESET +PD8.Signal=GPIO_Output +PD9.GPIOParameters=PinState,GPIO_Label +PD9.GPIO_Label=LED1 +PD9.PinState=GPIO_PIN_SET +PD9.Signal=GPIO_Output +PE0.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP +PE0.GPIO_Label=I2C2_SCL +PE0.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PE0.GPIO_PuPd=GPIO_NOPULL +PE0.Signal=GPIO_Output +PE1.GPIOParameters=GPIO_PuPd,GPIO_Label,GPIO_ModeDefaultOutputPP +PE1.GPIO_Label=I2C2_SDA +PE1.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD +PE1.GPIO_PuPd=GPIO_NOPULL +PE1.Signal=GPIO_Output +PE15.GPIOParameters=GPIO_PuPd,GPIO_Label +PE15.GPIO_Label=KEY_AUTO +PE15.GPIO_PuPd=GPIO_NOPULL +PE15.Signal=GPIO_Input +PE5.GPIOParameters=GPIO_Label +PE5.GPIO_Label=PWM_OUT +PE5.Signal=S_TIM3_CH3 +PE7.GPIOParameters=GPIO_Label +PE7.GPIO_Label=BP_A_PWR +PE7.Signal=GPIO_Output +PE8.GPIOParameters=GPIO_Label +PE8.GPIO_Label=BP_S_PWR +PE8.Signal=GPIO_Output +PE9.GPIOParameters=GPIO_Label +PE9.GPIO_Label=BP_B_PWR +PE9.Signal=GPIO_Output +PH0-OSC_IN\ (PH0).Mode=HSE-External-Oscillator +PH0-OSC_IN\ (PH0).Signal=RCC_OSC_IN +PH1-OSC_OUT\ (PH1).Mode=HSE-External-Oscillator +PH1-OSC_OUT\ (PH1).Signal=RCC_OSC_OUT +PinOutPanel.RotationAngle=0 +ProjectManager.AskForMigrate=true +ProjectManager.BackupPrevious=false +ProjectManager.CompilerOptimize=6 +ProjectManager.ComputerToolchain=false +ProjectManager.CoupleFile=true +ProjectManager.CustomerFirmwarePackage= +ProjectManager.DefaultFWLocation=true +ProjectManager.DeletePrevious=true +ProjectManager.DeviceId=STM32L476VGTx +ProjectManager.FirmwarePackage=STM32Cube FW_L4 V1.18.0 +ProjectManager.FreePins=true +ProjectManager.HalAssertFull=false +ProjectManager.HeapSize=0x800 +ProjectManager.KeepUserCode=true +ProjectManager.LastFirmware=true +ProjectManager.LibraryCopy=1 +ProjectManager.MainLocation=Core/Src +ProjectManager.NoMain=false +ProjectManager.PreviousToolchain= +ProjectManager.ProjectBuild=false +ProjectManager.ProjectFileName=controller-v2.ioc +ProjectManager.ProjectName=controller-v2 +ProjectManager.ProjectStructure= +ProjectManager.RegisterCallBack= +ProjectManager.StackSize=0x1000 +ProjectManager.TargetToolchain=MDK-ARM V5.32 +ProjectManager.ToolChainLocation= +ProjectManager.UAScriptAfterPath= +ProjectManager.UAScriptBeforePath= +ProjectManager.UnderRoot=false +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_DMA_Init-DMA-false-LL-true,4-MX_ADC1_Init-ADC1-false-LL-true,5-MX_TIM3_Init-TIM3-false-LL-true,6-MX_DAC1_Init-DAC1-false-LL-true,7-MX_SPI2_Init-SPI2-false-LL-true,8-MX_SPI1_Init-SPI1-false-LL-true,9-MX_TIM2_Init-TIM2-false-LL-true,10-MX_UART5_Init-UART5-false-LL-true,11-MX_USART1_UART_Init-USART1-false-LL-true,12-MX_TIM6_Init-TIM6-false-LL-true,13-MX_TIM7_Init-TIM7-false-LL-true,14-MX_I2C1_Init-I2C1-false-LL-true,15-MX_ADC2_Init-ADC2-false-LL-true +RCC.ADCFreq_Value=32000000 +RCC.AHBCLKDivider=RCC_SYSCLK_DIV8 +RCC.AHBFreq_Value=4000000 +RCC.APB1Freq_Value=4000000 +RCC.APB1TimFreq_Value=4000000 +RCC.APB2Freq_Value=4000000 +RCC.APB2TimFreq_Value=4000000 +RCC.CortexFreq_Value=4000000 +RCC.DFSDMFreq_Value=4000000 +RCC.FCLKCortexFreq_Value=4000000 +RCC.FamilyName=M +RCC.HCLKFreq_Value=4000000 +RCC.HSE_VALUE=8000000 +RCC.HSI_VALUE=16000000 +RCC.I2C1Freq_Value=4000000 +RCC.I2C2Freq_Value=4000000 +RCC.I2C3Freq_Value=4000000 +RCC.IPParameters=ADCFreq_Value,AHBCLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,CortexFreq_Value,DFSDMFreq_Value,FCLKCortexFreq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,HSI_VALUE,I2C1Freq_Value,I2C2Freq_Value,I2C3Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_VALUE,LSI_VALUE,MCO1PinFreq_Value,MSIClockRange,MSI_VALUE,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSAI2PoutputFreq_Value,PLLSAI2RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,PWR_Regulator_Voltage_Scale,RNGFreq_Value,SAI1Freq_Value,SAI2Freq_Value,SDMMCFreq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,UART4Freq_Value,UART5Freq_Value,USART1Freq_Value,USART2Freq_Value,USART3Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value,VCOSAI2OutputFreq_Value +RCC.LPTIM1Freq_Value=4000000 +RCC.LPTIM2Freq_Value=4000000 +RCC.LPUART1Freq_Value=4000000 +RCC.LSCOPinFreq_Value=32000 +RCC.LSE_VALUE=32768 +RCC.LSI_VALUE=32000 +RCC.MCO1PinFreq_Value=32000000 +RCC.MSIClockRange=RCC_MSIRANGE_8 +RCC.MSI_VALUE=16000000 +RCC.PLLPoutputFreq_Value=9142857.142857144 +RCC.PLLQoutputFreq_Value=32000000 +RCC.PLLRCLKFreq_Value=32000000 +RCC.PLLSAI1PoutputFreq_Value=9142857.142857144 +RCC.PLLSAI1QoutputFreq_Value=32000000 +RCC.PLLSAI1RoutputFreq_Value=32000000 +RCC.PLLSAI2PoutputFreq_Value=9142857.142857144 +RCC.PLLSAI2RoutputFreq_Value=32000000 +RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE +RCC.PREFETCH_ENABLE=1 +RCC.PWRFreq_Value=32000000 +RCC.PWR_Regulator_Voltage_Scale=PWR_REGULATOR_VOLTAGE_SCALE1 +RCC.RNGFreq_Value=32000000 +RCC.SAI1Freq_Value=9142857.142857144 +RCC.SAI2Freq_Value=9142857.142857144 +RCC.SDMMCFreq_Value=32000000 +RCC.SWPMI1Freq_Value=4000000 +RCC.SYSCLKFreq_VALUE=32000000 +RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK +RCC.UART4Freq_Value=4000000 +RCC.UART5Freq_Value=4000000 +RCC.USART1Freq_Value=4000000 +RCC.USART2Freq_Value=4000000 +RCC.USART3Freq_Value=4000000 +RCC.USBFreq_Value=32000000 +RCC.VCOInputFreq_Value=8000000 +RCC.VCOOutputFreq_Value=64000000 +RCC.VCOSAI1OutputFreq_Value=64000000 +RCC.VCOSAI2OutputFreq_Value=64000000 +SH.ADCx_IN11.0=ADC1_IN11,IN11-Single-Ended +SH.ADCx_IN11.ConfNb=1 +SH.ADCx_IN12.0=ADC1_IN12,IN12-Single-Ended +SH.ADCx_IN12.ConfNb=1 +SH.ADCx_IN13.0=ADC1_IN13,IN13-Single-Ended +SH.ADCx_IN13.ConfNb=1 +SH.ADCx_IN14.0=ADC1_IN14,IN14-Single-Ended +SH.ADCx_IN14.ConfNb=1 +SH.ADCx_IN5.0=ADC1_IN5,IN5-Single-Ended +SH.ADCx_IN5.1=ADC2_IN5,IN5-Single-Ended +SH.ADCx_IN5.ConfNb=2 +SH.ADCx_IN6.0=ADC1_IN6,IN6-Single-Ended +SH.ADCx_IN6.1=ADC2_IN6,IN6-Single-Ended +SH.ADCx_IN6.ConfNb=2 +SH.ADCx_IN7.0=ADC1_IN7,IN7-Single-Ended +SH.ADCx_IN7.ConfNb=1 +SH.ADCx_IN8.0=ADC1_IN8,IN8-Single-Ended +SH.ADCx_IN8.ConfNb=1 +SH.ADCx_IN9.0=ADC1_IN9,IN9-Single-Ended +SH.ADCx_IN9.ConfNb=1 +SH.COMP_DAC12_group.0=DAC1_OUT2,DAC_OUT2 +SH.COMP_DAC12_group.ConfNb=1 +SH.S_TIM2_CH4.0=TIM2_CH4,PWM Generation4 CH4 +SH.S_TIM2_CH4.ConfNb=1 +SH.S_TIM3_CH3.0=TIM3_CH3,PWM Generation3 CH3 +SH.S_TIM3_CH3.ConfNb=1 +SPI1.CLKPhase=SPI_PHASE_2EDGE +SPI1.CLKPolarity=SPI_POLARITY_HIGH +SPI1.CalculateBaudRate=2.0 MBits/s +SPI1.DataSize=SPI_DATASIZE_8BIT +SPI1.Direction=SPI_DIRECTION_2LINES +SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPolarity,CLKPhase +SPI1.Mode=SPI_MODE_MASTER +SPI1.VirtualType=VM_MASTER +SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2 +SPI2.CLKPolarity=SPI_POLARITY_LOW +SPI2.CalculateBaudRate=2.0 MBits/s +SPI2.DataSize=SPI_DATASIZE_8BIT +SPI2.Direction=SPI_DIRECTION_2LINES +SPI2.FirstBit=SPI_FIRSTBIT_LSB +SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,FirstBit,NSSPMode,BaudRatePrescaler,CLKPolarity +SPI2.Mode=SPI_MODE_MASTER +SPI2.NSSPMode=SPI_NSS_PULSE_DISABLE +SPI2.VirtualType=VM_MASTER +STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0.DSPOoLibraryJjLibrary_Checked=true +STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0.IPParameters=LibraryCcDSPOoLibraryJjDSPOoLibrary +STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0.LibraryCcDSPOoLibraryJjDSPOoLibrary=true +STMicroelectronics.X-CUBE-ALGOBUILD.1.3.0_SwParameter=LibraryCcDSPOoLibraryJjDSPOoLibrary\:true; +TIM2.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM2.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4 +TIM2.ClearChannel4=TIM_CHANNEL_4 +TIM2.ClearInputSource=TIM_CLEARINPUTSOURCE_NONE +TIM2.IPParameters=Channel-PWM Generation4 CH4,Period,AutoReloadPreload,ClearInputSource,ClearChannel4,Prescaler +TIM2.Period=3999 +TIM2.Prescaler=0 +TIM3.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3 +TIM3.IPParameters=Channel-PWM Generation3 CH3,Period,AutoReloadPreload,Prescaler +TIM3.Period=3999 +TIM3.Prescaler=0 +TIM6.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM6.IPParameters=Prescaler,Period,AutoReloadPreload +TIM6.Period=99 +TIM6.Prescaler=399 +TIM7.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE +TIM7.IPParameters=Prescaler,Period,AutoReloadPreload +TIM7.Period=99 +TIM7.Prescaler=399 +UART5.BaudRate=9600 +UART5.IPParameters=BaudRate +USART1.BaudRate=1200 +USART1.IPParameters=VirtualMode-Asynchronous,BaudRate,WordLength,Parity +USART1.Parity=PARITY_ODD +USART1.VirtualMode-Asynchronous=VM_ASYNC +USART1.WordLength=WORDLENGTH_9B +VP_ADC1_TempSens_Input.Mode=IN-TempSens +VP_ADC1_TempSens_Input.Signal=ADC1_TempSens_Input +VP_ADC1_Vref_Input.Mode=IN-Vrefint +VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input +VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0.Mode=DSPOoLibraryJjLibrary +VP_STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0.Signal=STMicroelectronics.X-CUBE-ALGOBUILD_VS_DSPOoLibraryJjLibrary_1.3.0_1.3.0 +VP_SYS_VS_Systick.Mode=SysTick +VP_SYS_VS_Systick.Signal=SYS_VS_Systick +VP_TIM2_VS_ClockSourceINT.Mode=Internal +VP_TIM2_VS_ClockSourceINT.Signal=TIM2_VS_ClockSourceINT +VP_TIM3_VS_ClockSourceINT.Mode=Internal +VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT +VP_TIM6_VS_ClockSourceINT.Mode=Enable_Timer +VP_TIM6_VS_ClockSourceINT.Signal=TIM6_VS_ClockSourceINT +VP_TIM7_VS_ClockSourceINT.Mode=Enable_Timer +VP_TIM7_VS_ClockSourceINT.Signal=TIM7_VS_ClockSourceINT +board=custom diff --git a/keilkill.bat b/keilkill.bat new file mode 100644 index 0000000..91ed224 --- /dev/null +++ b/keilkill.bat @@ -0,0 +1,30 @@ +del *.bak /s +del *.ddk /s +del *.edk /s +del *.lst /s +del *.lnp /s +del *.mpf /s +del *.mpj /s +del *.obj /s +del *.omf /s +::del *.opt /s ::不允许删除JLINK的设置 +del *.plg /s +del *.rpt /s +del *.tmp /s +del *.__i /s +del *.crf /s +del *.o /s +del *.d /s +del *.axf /s +del *.tra /s +del *.dep /s +del JLinkLog.txt /s + +del *.iex /s +del *.htm /s +del *.sct /s +del *.map /s + +del *.dbgconf /s +del *.uvguix.* /s +exit

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